1 Знакомство с R и RStudio
— Я вот не могу выбрать: делать на R или на Python?
— Да какая разница! Главное — делай!
1.1 Что это и откуда?
R — популярный язык программирования среди исследователей в социальных и гуманитарных науках. Если совсем коротко, то начиналось всё с языка S, который был языком программирования для статистического анализа. Потом его доработали и получился R.
Хотя сегодня всё ещё можно услышать, что «R — это язык программирования для статистической обработки данных», это ложь. Да, когда-то давно дела обстояли именно так, но сейчас R — это полноценный язык программирования, который позволяет решать широкий спект задач от статистического анализа и data wrangling до машинного обучения, моделирования и создания сайтов и приложений.
1.2 Почему R?
- свободное ПО (часть GNU Project)
- динамично развивается
- громадные возможности расширения функционала
- более 10 000 пакетов
- открытый исходный код
- возможность написать свои пакеты
- большое сообщество по всему миру, много ресурсов для задавания вопросов
- Linear Warriors vs Quadratic Wizards
- в SPSS (и другие GUI пакеты) ниже порог вхождения, но развитие навыков — линейное
- в R порог вхождения выше, но впоследствии случается резкий буст, и вы становитесь богами дата саенс
- репродуцируемость результатов
1.2.1 А он лучше Питона?
Нет. Но он и не хуже.
Вообще файт 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 Где спросить вопрос или искать ответ?
- Google — препарат выбора
- Stack Overflow — ответы на вопросы, и не только по R
- Stack Overflow на русском — то же самое, только отечественные специалисты
- Cookbook for R — хорошая книжка для старта
- RStudio Community — ответы на вопросы по R
- R-bloggers — про новинки в R и рядом с ним
- Хабр про R
- …
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 есть все привычные нам математические операции и операторы для них: +
, -
, *
, /
, ^
. Выполняются они тоже вполне предсказуемо:
## [1] 7
## [1] 6
## [1] 21
## [1] 10
## [1] 1024
Также есть два особых деления:
## [1] 2
## [1] 1
Попробуйте самостоятельно посчитать какие-нибудь простые примеры.
В R есть скобки — ()
. Их назначение такое же, как и в математике. Порядок выполнения арифметических действий (приоритет операторов4, operator precedence) тоже как в математике. Итого имеем:
## [1] 20
## [1] 32
## [1] 15625
## [1] 9765625
Так что используйте скобки, если вы не уверены, в каком порядке будут выполняться действия. Или смотрите таблицу приоритетор операторов по команде ?Syntax
.
1.7.2 Функции
Но что, если нам надо посчитать что-то более сложное? Например, извлечь корень или вычислить логарифм? С корнем мы можем провернуть математический финт, если вспомним, что \(\sqrt{x} = x^{\frac{1}{2}}\):
## [1] 2
Однако с логарифмом так уже не прокатит. Для вычисления подобных штук существуют функции. К вопросу, что есть функция, мы ещё не раз вернемся, а пока ограничимся самым общим пониманием: функция это некоторая команда, которая имеет вид название_функции()
, просит что-то указать у себя в скобках (например, число) и после выполнения возвращает нам некоторый ответ (например, снова число).
На примере с квадратным корнем это выглядит так:
## [1] 2
R чувствителен к регистру (case-sensitive), то есть
SQRT(4)
не сработает.
А вот логарифм:
## [1] 2.772589
Вот только здесь есть одна важная деталь.
Какая?
Если мы вспомним определение логарифма, то окажется, что \[\log_a b = c \Leftrightarrow a^c = b\] > Логарифм некоторого числа — это показатель степени, в которую нужно возвести основание, чтобы получить данное число.
Здесь придется чуть углубиться в аргументы функции. Аргументы — это то самое «что-то», что мы записываем в скобках. Бывают обязательные аргументы, без которых функция просто не будет работать и выдаст ошибку, например,
и необязательные аргументы, у которых уже задано некоторое значение по умолчанию, например, аргумент base
у функции log()
, который отвечает как раз за задание основания логарифма.
Список аргументов функции можно посмотреть в справке по данной функции, открыв окно Help и введя в поиск название функции, или выполнив одну из следующих команд:
Также в справке можно найти много другой полезной информации.
Какое значение по умолчанию определено для аргумента base
функции log()
?
Согласно хелпу, значение по умолчанию равно \(e\), то есть вычисляется натуральный логарифм, если основание не указано. Но подождите, в хелпе не написано никакого \(e\), там есть что-то странное в виде exp(1)
. Да, тут спросить бессмысленно, однако exp(1)
— это не что иное, как экспонента от единицы, то есть \(e^1 = e\), что равно:
## [1] 2.718282
Итак, мы выучили две важные вещи: (1) функцию exp()
и то, что (2) в качестве аргументов функции можно передавать результаты другой функции. Посмотрите примеры:
## [1] 4
## [1] 4
## [1] 4
## [1] 2
## [1] 1.960516
## [1] 3
## [1] 9
На логарифмах, естественно, свет клином не сошёлся, есть и множество других функций, например, тригонометрические (sin()
, cos()
, …). Да и сами арифметические операции, на самом деле, это тоже функции:
## [1] 10
К функциям, как я говорил, мы ещё вернемся, а пока двинемся дальше.
Но перед этим ещё одна важная деталь. Вы, наверняка, заметили, что после команд я часто пишу #
и далее текст. Это комментарии. Они крайне важны в коде, поэтому я, и не только я, настоятельно советую вам их оставлять — и чем больше, тем лучше. Сейчас это может казаться бессмысленным, но поверьте, когда ваш код будет занимать 50+ строк — а это очень небольшой код — разобраться уже будет непросто, не говоря о том, что делать, если вы открыли его через месяц или, не дай боже, год…
Закомментить несколько строк сразу можно сочетанием 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: >
, <
, >=
, <=
, ==
, !=
— больше, меньше, больше или равно, меньше или равно, равно (ли), не равно.
Обратите внимание, что сравнение на равенство осуществляется с помощью оператора
==
! Одинарное «равно» (=
) имеет другой смысл (см. ниже).
Посмотрим на ряд простых примеров:
## [1] FALSE
## [1] TRUE
## [1] TRUE
## [1] TRUE
## [1] TRUE
Вроде все логично и понятно. Единственное, что стоит помнить, это то, что приоритет операторов сравнения ниже, чем у арифметических операций.
Сделайте самостоятельно несколько простых сравнений.
Само по себе сравнение интуитивно понятно, однако нам интересен здесь получаемый результат. Ранее мы имели дело с числами — здесь что-то другое. С одно стороны, программы выдает на слово, но это не простое слово. Это особый тип данных — логическое значение («истина» TRUE
или «ложь» FALSE
). Типы данных и элементы алгебры логики мы подробно будем обсуждать далее, пока же снова ограничимся простым и интуитивным пониманием.
Мы можем составлять из простых сравнений сложные высказывания с помощью логических операторов. Самые известные и часто используемые из них — «И» (&
) и «ИЛИ» (|
). Подробно об их смысле здесь. Если в двух словах, то «И» истинно, когда оба соединяемых им утверждений истинны, а «ИЛИ» истинно, когда хотя бы одно из соединяемых им утвердений истинно. Например,
## [1] FALSE
## [1] TRUE
## [1] TRUE
## [1] TRUE
## [1] FALSE
Как видно из примеров, приоритет логических операторов ниже приоритета операторов сравнения, а приоритет у &
выше, чем у |
.
1.8 Assignment и переменные
Мы что-то считаем в R и нам важно не терять результаты вычислений. Для этого существуют переменные, в которые можно записывать промежуточные результаты. Делается это так:
В данном случае мы записали в переменную x
значение \(3\). Разберёмся подробно:
- Обозначаем название переменной, в данном случае
x
. На самом деле, название может быть любое, однако рекомендуется давать им осмысленные имена, чтобы потом не запутаться. Длинные названия — это, скорее, хорошо. Это немного съедает времени сейчас, но значительно экономит его в будущем! Также НЕ рекомендуется использовать для обозначения переменных названия функций (например,data()
,str()
и др). - Говорим, что надо записать в переменную значение или же присвоить какой-то результат функции. Делается это с помощью оператора присваивания (assignment)
<-
, который вводится с клавиатуры шорткатомAlt
+-
(Option
+-
). Этот оператор записывает то, что справа в то, что слева. - Пишем то, что нужно присвоить в переменную. Это может быть конкретное значение, но чаще это результат какой-либо функции, например:
После создания переменной, она появляется в Environment. Далее переменные можно использовать в вычислениях:
## [1] 3.893997
## [1] 24.03186
## [1] -0.1019953
## [1] FALSE
Обратите внимание ещё раз, что сравнивания переменные мы используем оператор ==
. А что будет если использовать одно «равно»?
## [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 во время работы. Что это за папка можно узнать через команду:
## [1] "/Users/antonangelgardt/hseuxlab-wlm2021/book/wlm2021-book"
У меня он смотрел вот в эту папку, у вас, скорее всего, будет что-то типа C://users/имя_пользователя
или /Users/имя_пользователя
, что указывает на папку пользователя по умолчанию.
Можно установить другую рабочую директорию с помощью команды setwd()
:
Теперь он будет смотреть в папку R
, которая лежит в дефолтной папке пользователя. Такой способ достаточно удобен, однако можно сделать ещё лучше — создать проект (Project).
Кто-то любит работать в проектах, кто-то нет — дело вкуса. Мне это нравится, даже если вам не понравится. Простите, если мы вдруг не сойдёмся во вкусах, но, повторюсь, это нравится мне, сугубо, лично… Поэтому я буду про это рассказывать и рекламировать.
Зайдите в File → New Project…
. У вас откроется такое окно:
Выберите New Directory
, затем еще раз New Project
:
Откроется вот это:
В Directory name
указываем название нашей папки, во втором поле указываем путь к той папке, в которой будет лежать создаваемая папка. Нажимаем Create Project
, после чего R перезапускает сессию, и открывается привычное окно. Однако в верхнем правом углу R теперь указано название проекта, в котором мы работаем.
Создайте проект для нашего курса.
- Откройте
File → New Project…
- Выберите
New Directory → New Project
- Назовите новую директорию
hseuxlab-wlm2021
- Задайте расположение внутри папки пользователя системы
- Создайте новый скрипт и скопируйте туда следующий код:
print("Hello, World of Linear Models!")
- Сохраните скрипт нажатием
Ctrl
+S
(Cmd
+S
)
Теперь при работе в рамках курса мы будем запускать проект и работать в нём, чтобы ничего не запуталось.
Много ли это приносит профита? Ну, не так уж и много… По сути, что открыть проект, что выполнить setwd("пусть_к_папке")
— примерно одно и то же. Вот только строку кода можно забыть запустить после открытия скрипта, а если мы запустили проект, мы уверены, что у нас все автоматически настроилось и ошибок не будет.
Откройте директорию (папку) проекта курса и создайте в ней несколько папок. Они нам понадобятся для структурирования нашего пространства в процессе курса, потому что файлов будет много. Кроме того, будем постепенно привыкать к тому, чтобы наше рабочее пространство было чистым и опрятным.
Нам понадобятся следующие папки:
scripts
для хранения скриптовых файловdata
для хранения файлов данныхfigures
, чтобы выгружать графики
Потом мы сможем дополнить их другими папками, если нам таковые понадобятся, а также создать более мелкие подразделы внутри созданных папок.
При первом запуске может не быть окна Code Editor. Чтобы его открыть, сделайте
File → New File → R Script
или нажмитеCtrl
+Shift
+N
(Cmd
+Shift
+N
).↩︎Чтобы не возникало лишних вопросов, лучше снабдить папку с файлами документом README.md, где описать все важные детали, в том числе и кодировку файла. Об это ещё немного поговорим поздее.↩︎
Бывает, что вот это распространяют и на калькуляторы тоже. [Кек]↩︎
А вообще в разных языках программирования этот вопрос решается по-разному.↩︎