1 Знакомство с R и RStudio

— Я вот не могу выбрать: делать на R или на Python?
— Да какая разница! Главное — делай!

1.1 Что это и откуда?

R — популярный язык программирования среди исследователей в социальных и гуманитарных науках. Если совсем коротко, то начиналось всё с языка S, который был языком программирования для статистического анализа. Потом его доработали и получился R.

Хотя сегодня всё ещё можно услышать, что «R — это язык программирования для статистической обработки данных», это ложь. Да, когда-то давно дела обстояли именно так, но сейчас R — это полноценный язык программирования, который позволяет решать широкий спект задач от статистического анализа и data wrangling до машинного обучения, моделирования и создания сайтов и приложений.

1.2 Почему R?

  • свободное ПО (часть GNU Project)
  • динамично развивается
  • громадные возможности расширения функционала
    • более 10 000 пакетов
    • открытый исходный код
    • возможность написать свои пакеты

      Source

  • большое сообщество по всему миру, много ресурсов для задавания вопросов
  • Linear Warriors vs Quadratic Wizards
    • в SPSS (и другие GUI пакеты) ниже порог вхождения, но развитие навыков — линейное
    • в R порог вхождения выше, но впоследствии случается резкий буст, и вы становитесь богами дата саенс

Source

1.2.1 А он лучше Питона?

Source

Нет. Но он и не хуже.

Вообще файт R vs Python, на мой взгляд, несколько бессмысленный, поскольку, по факту, всё упирается в синтаксис языка. Ну, и запрос работодателя, конечно. Возможности обоих языков и скорость работы сопоставимы. Области применения по большей части тоже. Поэтому я пользуюсь следующей эвристикой:

  • аналитика, статистика, графики, покрутить данные — R
  • машинное обучение, нейросети, другой ИИ, интерфейсы и [собственно] программирование — Python

Многие, наверняка, оспорят такое разделение — я же не стану отстаивать его истинность.

Мы будем работать на R, поскольку он всё же более популярен в наших кругах — среди «социально-гуманитарных аналитиков».

1.3 Установка R и RStudio

Чтобы нам радостно и приятно жилось, нужно установить:

Если что-то не установилось или вы предпочитаете облачные сервисы, то можно работать через браузер в RStudio Cloud.

1.3.1 А зачем обе штуки ставить?

Вопрос не безосновательный. Не углубляясь в мелкие детали, скажем так: R — это собственно язык программирования, а RStudio — это среда (IDE, integrated development environment), которая позволяет в этом языке удобно и просто работать, а также расширяет его возможности.

RStudio — не единственная среда для работы в R, но, определённо, самая топовая. Почти все пользуются именно ею, и нет смысла искать что-то более удобное.

1.4 Где спросить вопрос или искать ответ?

1.5 Интерфейс R

Можно, конечно, работать и без RStudio вовсе — чисто в R. Мы кратенько взглянем на его интерфейс, чтобы наслаждение от встречи с IDE-шкой было больше.

Выглядит весьма по-программистски. Есть окно скрипта, где пишутся команды, есть консоль, в которой они выполняются, иногда открываются окна с графиками. Но, в общем, посмотрели для общего развития — и хватит. Пора серьезными делами заняться.

1.6 Интерфейс RStudio

Итак, посмотрим на RStudio. При запуске у вас откроется что-то такое:

Видно четыре (или три1) окна. Давайте последовательно разбираться, что в каждом из них происходит.

1.6.1 Console

В консоль можно писать команды и запускать их нажатием Enter. Они будут сразу выполняться. После некоторых команд будет выводиться какой-то результат. С помощью стрелок и можно вывести предыдущие команды, например, чтобы запустить их ещё раз, не вводя повторно, или каким-либо образом их изменить.

Можно, в прицнипе, работать только из консоли, но на практике это не очень удобно. Главным образом, из-за того, что команды улетают «вникуда» и к некоторым уже будет нельзя вернуться. Поэтому существует редактор кода.

1.6.2 Code Editor

По своей сути это обычный блокнот с той лишь разницей, что здесь некоторые слова раскрашены. И в этом блокноте мы пишем текст программы (скрипт), который состоит из комманд. Чтобы выполнить команду, нам необхожимо отправить её в консоль с помощью Ctrl + Enter (Cmd + Enter). Нажатие Enter здесь как и в обычном текстовом редакторе осуществляет переход на новую строку. Результат выполнения команды отображается в консоли, как будто вы изначально запускали команду там.

В консоли удобно что-то быстро поститать, скрипт же удобнее при работе с длинными командами и для сохранения кода (текста) для дальнейшей работы. Чтобы сохранить скрипт, сделайте File → Save (as…) или нажмите Ctrl + S (Cmd + S).

Несмотря на то, что файл сохраняется с расширением .R, это всё ещё обычный текст, который можно открыть и редактировать в любом текстовом редакторе (типа Notebook или TextEdit).

К вопросу текста мы ещё вернёмся.

1.6.2.1 Кодировка

Компьютер умеет хранить в памяти только цифры. А текст мы набираем буквами. Поэтому ему приходится перекодировать буквы в цифры. Делать это можно по-разному — поэтому существуют разные кодировки.

При сохранении скрипта важно следить за кодировкой, особенно если в тексте встречаются кириллические знаки. В разных операционных систем разная кодировка по умолчанию, поэтому на другом компьютере файл может открываться с неведомой кракозяброй типа этой:

Обычно при сохрании файла с кириллицей программа автоматически спрашивает, в какой кодировке его надо сохранить. Выбирайте UTF-8 — она корректно откроется в любой операционной системе. Также вы можете сохранить файл в определенной кодировке в помощью File → Save with Encoding….

Если при открытии файла у вас отображается кракозябра, подобная той, которая показана выше, нужно узнать кодировку файла2 (для Win это обычно ASCII, для Mac — UTF-8) и выполнить File → Reopen with Encoding….

1.6.3 Environment (Workspace) и History

Здесь, в Environment, можно наблюдать переменные и другие объекты, которые создаются в процессе работы кода, а также некоторую информацию о них. Это удобно, поскольку код, бывает, разрастается до сумасшедшего количества строк, и что вы там насоздавали тремястами строками выше — уже и не упомнить. А тут всё под рукой.

В окне History можно найти историю команд, которые вы выполняли. Может быть полезно, чтобы не листать консоль, которая, как правило, завалена результатами и ошибками.

1.6.4 Plots, Files, Packages, Help, Viewer

Очень полезное окно в кучей всего.

  • сюда выводятся графики, которые вы строите
  • здесь можно найти справку по функциям и пакетам
  • проверить, какие у вас установлены пакеты и их версии
  • посмотреть файлы в рабочей директории
  • наблюдать 3D-визуализации, превью отчетов, презентаций и много чего ещё

1.7 R как калькулятор

R — полноценный язык программирования с множеством возможностей, но давайте начнём с малого. Первое, от чего стоит избавиться — это страх консоли. Боязни калькулятора вроде не бывает (но это не точно3), поэтому стартанём с этого.

1.7.1 Арифметические операции

В R есть все привычные нам математические операции и операторы для них: +, -, *, /, ^. Выполняются они тоже вполне предсказуемо:

2 + 5 # сложение
## [1] 7
10 - 4 # вычитание
## [1] 6
3 * 7 # умножение
## [1] 21
30 / 3 # деление
## [1] 10
2 ^ 10 # возведение в степень
## [1] 1024

Также есть два особых деления:

5 %/% 2 # целочисленное деление
## [1] 2
5 %% 2 # взятие остатка от деления (5 mod 2)
## [1] 1

Попробуйте самостоятельно посчитать какие-нибудь простые примеры.

Source

В R есть скобки — (). Их назначение такое же, как и в математике. Порядок выполнения арифметических действий (приоритет операторов4, operator precedence) тоже как в математике. Итого имеем:

4 * 4 + 4
## [1] 20
4 * (4 + 4)
## [1] 32
5 * 5 ^ 5
## [1] 15625
(5 * 5) ^ 5
## [1] 9765625

Так что используйте скобки, если вы не уверены, в каком порядке будут выполняться действия. Или смотрите таблицу приоритетор операторов по команде ?Syntax.

1.7.2 Функции

Но что, если нам надо посчитать что-то более сложное? Например, извлечь корень или вычислить логарифм? С корнем мы можем провернуть математический финт, если вспомним, что \(\sqrt{x} = x^{\frac{1}{2}}\):

4 ^ 0.5
## [1] 2

Однако с логарифмом так уже не прокатит. Для вычисления подобных штук существуют функции. К вопросу, что есть функция, мы ещё не раз вернемся, а пока ограничимся самым общим пониманием: функция это некоторая команда, которая имеет вид название_функции(), просит что-то указать у себя в скобках (например, число) и после выполнения возвращает нам некоторый ответ (например, снова число).

На примере с квадратным корнем это выглядит так:

sqrt(4)
## [1] 2

R чувствителен к регистру (case-sensitive), то есть SQRT(4) не сработает.

А вот логарифм:

log(16)
## [1] 2.772589

Вот только здесь есть одна важная деталь.

Какая?

Если мы вспомним определение логарифма, то окажется, что \[\log_a b = c \Leftrightarrow a^c = b\] > Логарифм некоторого числа — это показатель степени, в которую нужно возвести основание, чтобы получить данное число.

Здесь придется чуть углубиться в аргументы функции. Аргументы — это то самое «что-то», что мы записываем в скобках. Бывают обязательные аргументы, без которых функция просто не будет работать и выдаст ошибку, например,

log() # попробуйте выполнить эту команду

и необязательные аргументы, у которых уже задано некоторое значение по умолчанию, например, аргумент base у функции log(), который отвечает как раз за задание основания логарифма.

Список аргументов функции можно посмотреть в справке по данной функции, открыв окно Help и введя в поиск название функции, или выполнив одну из следующих команд:

help(log) # ищет справку по функции
?log # синоним предыдущей команды

Также в справке можно найти много другой полезной информации.

Какое значение по умолчанию определено для аргумента base функции log()?

Согласно хелпу, значение по умолчанию равно \(e\), то есть вычисляется натуральный логарифм, если основание не указано. Но подождите, в хелпе не написано никакого \(e\), там есть что-то странное в виде exp(1). Да, тут спросить бессмысленно, однако exp(1) — это не что иное, как экспонента от единицы, то есть \(e^1 = e\), что равно:

exp(1)
## [1] 2.718282

Итак, мы выучили две важные вещи: (1) функцию exp() и то, что (2) в качестве аргументов функции можно передавать результаты другой функции. Посмотрите примеры:

log(x = 16, base = 2) # эксплицитно задаём основание и число
## [1] 4
log(x = 16, b = 2) # имена аргументов можно не дописывать, если они не совпадают с другими
## [1] 4
log(base = 2, x = 16) # при таком способе задания порядок аргументов можно менять
## [1] 4
log(625, 25) # имя аргумента можно не писать, но тогда соблюдать порядок следования
## [1] 2
log(16, base = exp(sqrt(2))) # задаём аргумент через результат функций
## [1] 1.960516
log10(1000) # десятичный логарифм
## [1] 3
log2(512) # двоичный логарифм
## [1] 9

На логарифмах, естественно, свет клином не сошёлся, есть и множество других функций, например, тригонометрические (sin(), cos(), …). Да и сами арифметические операции, на самом деле, это тоже функции:

'+'(7, 3)
## [1] 10

К функциям, как я говорил, мы ещё вернемся, а пока двинемся дальше.

Но перед этим ещё одна важная деталь. Вы, наверняка, заметили, что после команд я часто пишу # и далее текст. Это комментарии. Они крайне важны в коде, поэтому я, и не только я, настоятельно советую вам их оставлять — и чем больше, тем лучше. Сейчас это может казаться бессмысленным, но поверьте, когда ваш код будет занимать 50+ строк — а это очень небольшой код — разобраться уже будет непросто, не говоря о том, что делать, если вы открыли его через месяц или, не дай боже, год…

Source

Закомментить несколько строк сразу можно сочетанием Ctrl + Shift + C (Cmd + Shift + C).

Посчитайте в R значения следующих выражений. Для проверки введите неокруглённое значение до четвёртого знака после запятой.

  • \((\log_3 65)^7\)
  • \(e^\sqrt[3]{5.5}\)
  • \(\sin(8\pi + 4)\)
  • \(\log \cos(-5\sqrt{12})\)
  • \(\displaystyle 2\tan \log_{\sqrt{3}}8 + \sin^{(20\! \mod\! 3)} \Big(e + \frac{8}{3}\Big)\)

1.7.3 Сравнение и логические операции

Как мы знаем, числа можно сравнивать. Также мы знаем, что существуют операторы сравнения — все они есть и в R: >, <, >=, <=, ==, != — больше, меньше, больше или равно, меньше или равно, равно (ли), не равно.

Обратите внимание, что сравнение на равенство осуществляется с помощью оператора ==! Одинарное «равно» (=) имеет другой смысл (см. ниже).

Посмотрим на ряд простых примеров:

2 > 4
## [1] FALSE
2 < 6
## [1] TRUE
3 == 5 - 2
## [1] TRUE
7 >= 7
## [1] TRUE
4 != 8 ^ 2
## [1] TRUE

Вроде все логично и понятно. Единственное, что стоит помнить, это то, что приоритет операторов сравнения ниже, чем у арифметических операций.

Сделайте самостоятельно несколько простых сравнений.

Само по себе сравнение интуитивно понятно, однако нам интересен здесь получаемый результат. Ранее мы имели дело с числами — здесь что-то другое. С одно стороны, программы выдает на слово, но это не простое слово. Это особый тип данных — логическое значение («истина» TRUE или «ложь» FALSE). Типы данных и элементы алгебры логики мы подробно будем обсуждать далее, пока же снова ограничимся простым и интуитивным пониманием.

Мы можем составлять из простых сравнений сложные высказывания с помощью логических операторов. Самые известные и часто используемые из них — «И» (&) и «ИЛИ» (|). Подробно об их смысле здесь. Если в двух словах, то «И» истинно, когда оба соединяемых им утверждений истинны, а «ИЛИ» истинно, когда хотя бы одно из соединяемых им утвердений истинно. Например,

2 > 6 & 8 < 12
## [1] FALSE
1 != 4 & 5 == 10 / 2
## [1] TRUE
6 + 2 < 10 | 8 == 10 # что по сути эквивалентно 8 <= 10
## [1] TRUE
1 + 1 == 2 | FALSE & 4 != 2 * 2
## [1] TRUE
(1 + 1 == 2 | FALSE) & 4 != 2 * 2
## [1] FALSE

Как видно из примеров, приоритет логических операторов ниже приоритета операторов сравнения, а приоритет у & выше, чем у |.

1.8 Assignment и переменные

Мы что-то считаем в R и нам важно не терять результаты вычислений. Для этого существуют переменные, в которые можно записывать промежуточные результаты. Делается это так:

x <- 3

В данном случае мы записали в переменную x значение \(3\). Разберёмся подробно:

  1. Обозначаем название переменной, в данном случае x. На самом деле, название может быть любое, однако рекомендуется давать им осмысленные имена, чтобы потом не запутаться. Длинные названия — это, скорее, хорошо. Это немного съедает времени сейчас, но значительно экономит его в будущем! Также НЕ рекомендуется использовать для обозначения переменных названия функций (например, data(), str() и др).
  2. Говорим, что надо записать в переменную значение или же присвоить какой-то результат функции. Делается это с помощью оператора присваивания (assignment) <-, который вводится с клавиатуры шорткатом Alt + - (Option + -). Этот оператор записывает то, что справа в то, что слева.
  3. Пишем то, что нужно присвоить в переменную. Это может быть конкретное значение, но чаще это результат какой-либо функции, например:
y <- sin(90)

После создания переменной, она появляется в Environment. Далее переменные можно использовать в вычислениях:

x + y
## [1] 3.893997
x^y * x^2
## [1] 24.03186
log(y, x)
## [1] -0.1019953
x == y
## [1] FALSE

Обратите внимание ещё раз, что сравнивания переменные мы используем оператор ==. А что будет если использовать одно «равно»?

x = y
x
## [1] 0.8939967

Выполнилась операция присваивания. Да, её можно записывать и через «равно», но это не очень принято. Традиционно <- используют для присваивания, а = для задания аргументов функций. У оператора присваивания самый низкий приоритет из всех, то есть присваивание выполняется после всех вычислений. Хм, как неожиданно и логично.

Запишите в переменную k значение следующего выражения:

9^sqrt(8) + log(3,6)

в переменную l значение такого выражения:

(TRUE | FALSE) & (FALSE & TRUE)

в переменную m значение вот этого выражения:

6 >= 4 & 8 - 1 != 7 | sqrt(25) == 5

и в переменную n результат вот такой страшной команды:

read.csv("https://raw.githubusercontent.com/angelgardt/hseuxlab-wlm2021/master/book/wlm2021-book/data/Rintro_logic.csv")[['x']]

Какой результаты выдают следующие команды?

  • k & l
  • k & m
  • m & l | ((k & l) | m)
  • k & l & n
  • (1 | 2) & 0

1.9 Рабочая директория. Projects

В ходе нализа данных мы работаем со множеством файлов: скрипты, файлы сырых данных данных, файлы предобработанны данных, файл объектов из рабочего пространства, графики, результаты анализа… Это всё куда-то надо сохранять — вопрос куда?

В R есть понятие рабочей директории. Директория — это синоним папки. Рабочая директория — это папка, в которую смотрит R во время работы. Что это за папка можно узнать через команду:

getwd() # get working directory
## [1] "/Users/antonangelgardt/hseuxlab-wlm2021/book/wlm2021-book"

У меня он смотрел вот в эту папку, у вас, скорее всего, будет что-то типа C://users/имя_пользователя или /Users/имя_пользователя, что указывает на папку пользователя по умолчанию.

Можно установить другую рабочую директорию с помощью команды setwd():

setwd("/Users/antonangelgardt/R")

Теперь он будет смотреть в папку R, которая лежит в дефолтной папке пользователя. Такой способ достаточно удобен, однако можно сделать ещё лучше — создать проект (Project).

Кто-то любит работать в проектах, кто-то нет — дело вкуса. Мне это нравится, даже если вам не понравится. Простите, если мы вдруг не сойдёмся во вкусах, но, повторюсь, это нравится мне, сугубо, лично… Поэтому я буду про это рассказывать и рекламировать.

Зайдите в File → New Project…. У вас откроется такое окно:

Выберите New Directory, затем еще раз New Project:

Откроется вот это:

В Directory name указываем название нашей папки, во втором поле указываем путь к той папке, в которой будет лежать создаваемая папка. Нажимаем Create Project, после чего R перезапускает сессию, и открывается привычное окно. Однако в верхнем правом углу R теперь указано название проекта, в котором мы работаем.

Создайте проект для нашего курса.

  1. Откройте File → New Project…
  2. Выберите New Directory → New Project
  3. Назовите новую директорию hseuxlab-wlm2021
  4. Задайте расположение внутри папки пользователя системы
  5. Создайте новый скрипт и скопируйте туда следующий код:
print("Hello, World of Linear Models!")
  1. Сохраните скрипт нажатием Ctrl + S (Cmd + S)

Теперь при работе в рамках курса мы будем запускать проект и работать в нём, чтобы ничего не запуталось.

Много ли это приносит профита? Ну, не так уж и много… По сути, что открыть проект, что выполнить setwd("пусть_к_папке") — примерно одно и то же. Вот только строку кода можно забыть запустить после открытия скрипта, а если мы запустили проект, мы уверены, что у нас все автоматически настроилось и ошибок не будет.

Откройте директорию (папку) проекта курса и создайте в ней несколько папок. Они нам понадобятся для структурирования нашего пространства в процессе курса, потому что файлов будет много. Кроме того, будем постепенно привыкать к тому, чтобы наше рабочее пространство было чистым и опрятным.

Нам понадобятся следующие папки:

  • scripts для хранения скриптовых файлов
  • data для хранения файлов данных
  • figures, чтобы выгружать графики

Потом мы сможем дополнить их другими папками, если нам таковые понадобятся, а также создать более мелкие подразделы внутри созданных папок.


  1. При первом запуске может не быть окна Code Editor. Чтобы его открыть, сделайте File → New File → R Script или нажмите Ctrl + Shift + N (Cmd + Shift + N).↩︎

  2. Чтобы не возникало лишних вопросов, лучше снабдить папку с файлами документом README.md, где описать все важные детали, в том числе и кодировку файла. Об это ещё немного поговорим поздее.↩︎

  3. Бывает, что вот это распространяют и на калькуляторы тоже. [Кек]↩︎

  4. А вообще в разных языках программирования этот вопрос решается по-разному.↩︎