2 Введение в R

2.1 Установка R и Rstudio

Для работы с R необходимо его сначала скачать и установить.

  • R
    • на Windows, найдите большую кнопку Download R (номер версии) for Windows.
    • на Mac, если маку меньше, чем 5 лет, то смело ставьте *.pkg файл с последней версией. Если старше, то поищите на той же странице версию для вашей системы.
    • на Linux, также можно добавить зеркало и установить из командной строки:
sudo apt-get install r-cran-base

В данной книге используется следующая версия R:

sessionInfo()$R.version$version.string
## [1] "R version 4.0.2 (2020-06-22)"

После установки R необходимо скачать и установить RStudio:

Если вдруг что-то установить не получается (или же вы просто не хотите устанавливать на компьютер лишние программы), то можно работать в облаке, делая все то же самое в веб-браузере:

Первый и вполне закономерный вопрос: зачем мы ставили R и отдельно еще какой-то RStudio? Если опустить незначительные детали, то R — это сам язык программирования, а RStudio — это среда (IDE), которая позволяет в этом языке очень удобно работать.

RStudio — это не единственная среда для R, но, определенно, самая удобная на сегодняшний день. Почти все пользуются именно ею и не стоит тратить время на поиск чего-то более удобного и лучшего. Если же вы привыкли работать с Jupyter Notebook, то в R обычно вместо него используется великолепный RMarkdown — с помощью которого и написан этот онлайн-учебник, кстати говоря. И с RMarkdown мы тоже будем разбираться!

2.2 Знакомство с RStudio

Так, давайте взглянем на то, что нам тут открылось:

В первую очередь нас интересуют два окна: 1 - Code Editor (окно для написания скриптов)1 и 2 - R Console (консоль). Здесь можно писать команды и запускать их. При этом работа в консоли и работа со скриптом немного различается.

В 2 - R Console вы пишите команду и запускаете ее нажиманием Enter. Иногда после запуска команды появляется какой-то результат. Если нажимать стрелку вверх на клавиатуре, то можно выводить в консоль предыдущие команды. Это очень удобно для запуска предыдущих команд с небольшими изменениями.

В 1 - Code Editor для запуска команды вы должны выделить ее и нажать Ctrl + Enter (Cmd + Enter на macOS). Если не нажать эту комбинацию клавиш, то команда не запустится. Можно выделить и запустить сразу несколько команд или даже все команды скрипта. Все команды скрипта можно выделить с помощью сочетания клавиш Ctrl + A на Windows и Linux, Cmd + A на macOS.2 Как только вы запустите команду (или несколько команд), соответствующие строчки кода появятся в 2 - R Console, как будто бы вы запускали их прямо там.

Обычно в консоли удобно что-то писать, чтобы быстро что-то посчитать. Скрипты удобнее при работе с длинными командами и как способ сохранения написанного кода для дальнейшей работы. Для сохранения скрипта нажмите File - Save As.... R скрипты сохраняются с разрешением .R, но по своей сути это просто текстовые файлы, которые можно открыть и модифицировать в любом текстовом редакторе а-ля “Блокнот.”

3 - Workspace and History — здесь можно увидеть переменные. Это поле будет автоматически обновляться по мере того, как Вы будете запускать строчки кода и создавать новые переменные. Еще там есть вкладка с историей всех команд, которые были запущены.

4 - Plots and files. Здесь есть очень много всего. Во-первых, небольшой файловый менеджер, во-вторых, там будут появляться графики, когда вы будете их рисовать. Там же есть вкладка с вашими пакетами (Packages) и Help по функциям. Но об этом потом.

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

R — полноценный язык программирования, который позволяет решать широкий спектр задач. Но в первую очередь R используется для анализа данных и статистических вычислений. Тем не менее, многими R до сих пор воспринимается как просто продвинутый калькулятор. Ну что ж, калькулятор, так калькулятор.

Давайте начнем с самого простого и попробуем использовать R как калькулятор с помощью арифметических операторов +, -, *, /, ^ (степень), () и т.д.

Просто запускайте в консоли пока не надоест:

40+2
## [1] 42
3-2
## [1] 1
5*6
## [1] 30
99/9 #деление
## [1] 11
2^3 #степень
## [1] 8
13 %/% 3 #целочисленное деление
## [1] 4
13 %% 3 #остаток от деления
## [1] 1

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

Ничего сложного, верно? Вводим выражение и получаем результат.

Вы могли заметить, что некоторые команды у меня заканчиваются знаком решетки (#). Все, что написано в строчке после # игнорируется R при выполнении команды. Написанные команды в скрипте рекомендуется сопровождать комментариями, которые будут объяснять вам же в будущем (или кому-то еще), что конкретно происходит в соответствующем куске кода.3 Кроме того, комментарии можно использовать в тех случаях, когда вы хотите написать кусок кода по-другому, не стирая полностью предыдущий код: достаточно “закомментить” нужные строчки - поставить # в начало каждой строки, которую вы хотите переписать. Для этого есть специальное сочетание горячих клавиш: Ctrl + Shift + C (Cmd + Shift + C на macOS) — во всех выделенных строчках будет написан # в начале.

Согласно данным навязчивых рекламных баннеров в интернете, только 14% россиян могут справиться с этим примером:

2 + 2 * 2
## [1] 6

На самом деле, разные языки программирования ведут себя по-разному в таких ситуациях, поэтому ответ 6 (сначала умножаем, потом складываем) не так очевиден.

Порядок выполнения арифметических операций (т.е. приоритет операторов, operator precedence) в R как в математике, так что не забывайте про скобочки.

(2+2)*2
## [1] 8

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

2.4 Функции

Давайте теперь извлечем корень из какого-нибудь числа. В принципе, тем, кто помнит школьный курс математики, возведения в степень вполне достаточно:

16 ^ 0.5
## [1] 4

Ну а если нет, то можете воспользоваться специальной функцией: это обычно какие-то буквенные символы с круглыми скобками сразу после названия функции. Мы подаем на вход (внутрь скобочек) какие-то данные, внутри этих функций происходят какие-то вычисления, которые выдает в ответ какие-то другие данные (или же функция записывает файл, рисует график и т.д.).

Вот, например, функция для корня:

sqrt(16)
## [1] 4

R — case-sensitive язык, т.е. регистр важен. SQRT(16) не будет работать.

А вот так выглядит функция логарифма:

log(8)
## [1] 2.079442

Так, вроде бы все нормально, но… Если Вы еще что-то помните из школьной математики, то должны понимать, что что-то здесь не так.

Здесь не хватает основания логарифма!

Логарифм — показатель степени, в которую надо возвести число, называемое основанием, чтобы получить данное число.

То есть у логарифма 8 по основанию 2 будет значение 3:

\(\log_2 8 = 3\)

То есть если возвести 2 в степень 3 у нас будет 8:

\(2^3 = 8\)

Только наша функция считает все как-то не так.

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

?log

Справа внизу в RStudio появится вот такое окно:

Действительно, у этой функции есть еще аргумент base =. По умолчанию он равен числу Эйлера (2.7182818…), т.е. функция считает натуральный логарифм. В большинстве функций R есть какой-то основной инпут — данные в том или ином формате, а есть и дополнительные параметры, которые можно прописывать вручную, если параметры по умолчанию вас не устраивают.

log(x = 8, base = 2)
## [1] 3

…или просто (если Вы уверены в порядке переменных):

log(8,2)
## [1] 3

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

log(8, sqrt(4))
## [1] 3

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

log(base = 2, x = 8)
## [1] 3

А еще можно писать имена аргументов не полностью, если они не совпадают с другими:

log(b = 2, x = 8)
## [1] 3

Мы еще много раз будем возвращаться к функциям. Вообще, функции — это одна из важнейших штук в R (примерно так же как и в Python). Мы будем создавать свои функции, использовать функции как инпут для функций и многое-многое другое. В R очень крутые возможности работы с функциями. Поэтому подружитесь с функциями, они клевые.

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

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

2.5 В любой непонятной ситуации — гуглите

Если вдруг вы не знаете, что искать в хэлпе, или хэлпа попросту недостаточно, то… гуглите!

Нет ничего постыдного в том, чтобы гуглить решения проблем. Это абсолютно нормально. Используйте силу интернета во благо и да помогут вам Stackoverflow4 и бесчисленные R-туториалы!

Главное, помните: загуглить работающий ответ всегда недостаточно. Надо понять, как и почему решение работает. Иначе что-то обязательно пойдет не так.

Кроме того, правильно загуглить проблему — не так уж и просто.

Короче говоря: гуглить — хорошо, бездумно копировать чужие решения — плохо.

2.6 Переменные

Важная штука в программировании на практически любом языке — возможность сохранять значения в переменных. В R это обычно делается с помощью вот этих символов: <- (но можно использовать и обычное =, хотя это не очень принято). Для этого есть удобное сочетание клавиш: нажмите одновременно Alt + - (или option + - на macOS).

Заметьте, при присвоении результат вычисления не выводится в консоль! Если опустить детали, то обычно результат выполнения комманды либо выводится в консоль, либо записывается в переменную.

a <- 2
a
## [1] 2

Справа от <- находится значение, которое вы хотите сохранить, или же какое-то выражение, результат которого вы хотите сохранить в эту переменную5:

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

Нельзя: - new variable - _new_variable - .1var - v-r

Можно: - new_variable - .new.variable - var_2

Обязательно делайте названия переменных осмысленными! Старайтесь делать при этом их понятными и короткими, это сохранит вам очень много времени, когда вы (или кто-то еще) будете пытаться разобраться в написанном ранее коде. Если название все-таки получается длинным и состоящим из нескольких слов, то лучше всего использовать нижнее подчеркивание в качестве разделителя: some_variable6.

После присвоения переменная появляется во вкладке Environment в RStudio:

Можно использовать переменные в функциях и просто вычислениях:

b <- a ^ a + a * a
b
## [1] 8
log(b, a)
## [1] 3

2.7 Логические операторы

Вы можете сравнивать разные переменные:

a == b
## [1] FALSE

Заметьте, что сравнивая две переменные мы используем два знака равно ==, а не один =. Иначе это будет означать присвоение.

a = b
a
## [1] 8

Теперь Вы сможете понять комикс про восстание роботов на следующей странице (пусть он и совсем про другой язык программирования)

Этот комикс объясняет, как важно не путать присваивание и сравнение (хотя я иногда путаю до сих пор =( ).

Иногда нам нужно проверить на неравенство:

a <- 2
b <- 3

a == b
## [1] FALSE
a != b
## [1] TRUE

Восклицательный язык в программировании вообще и в R в частности стандартно означает отрицание.

Еще мы можем сравнивать на больше/меньше:

a > b
## [1] FALSE
a < b
## [1] TRUE
a >= b
## [1] FALSE
a <= b
## [1] TRUE

Этим мы будем пользоваться в дальнейшем регулярно! Именно на таких простых логических операциях построено большинство операций с данными.

##Типы данных {#data_types}

До этого момента мы работали только с числами (numeric):

class(a)
## [1] "numeric"

На самом деле, в R три типа numeric: integer (целые), double (дробные), complex (комплексные числа)7. R сам будет конвертировать числа в нужный тип numeric при необходимости, поэтому этим можно не заморачиваться.

Если же все-таки нужно задать конкретный тип числа эксплицитно, то можно воспользоваться функциями as.integer(), as.double() и as.complex(). Кроме того, при создании числа можно поставить в конце L, чтобы обозначить число как integer:

is.integer(5)
## [1] FALSE
is.integer(5L)
## [1] TRUE

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

sqrt(2)^2 == 2
## [1] FALSE

Это довольно стандартная ситуация, характерная не только для R. Чтобы ее избежать, можно воспользоваться функцией all.equal():

all.equal(sqrt(2)^2, 2)
## [1] TRUE

Теперь нам нужно ознакомиться с двумя другими важными типами данных в R:

  1. Строковые (character) данные: набор букв, цифр и символов, которые должны выделяться кавычками.
s <- "Всем привет!"
s
## [1] "Всем привет!"
class(s)
## [1] "character"

Можно использовать как ", так и ' (что удобно, когда строчка внутри уже содержит какие-то кавычки).

"Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn"
## [1] "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn"
  1. Логические (logical) данные: просто TRUE или FALSE.
t1 <- TRUE
f1 <- FALSE

t1
## [1] TRUE
f1
## [1] FALSE

Вообще, можно еще писать T и F (но не True и False!)

t2 <- T
f2 <- F

Это плохая практика, так как R защищает от перезаписи переменные TRUE и FALSE, но не защищает от этого T и F.

TRUE <- FALSE
## Error in TRUE <- FALSE: неправильная (do_set) левая сторона в присвоении
TRUE
## [1] TRUE
T <- FALSE
T
## [1] FALSE

Функция rm() позволяет удалить ненужную переменную:

rm(T)

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

comparison <- a == b
comparison
## [1] FALSE

Это нам очень понадобится, когда мы будем работать с реальными данными: нам нужно будет постоянно вытаскивать какие-то данные из датасета, что как раз и построено на игре со сравнением переменных.
Чтобы этим хорошо уметь пользоваться, нам нужно еще освоить как работать с логическими операторами. Про один мы немного уже говорили — это логическое НЕ (!). ! превращает TRUE в FALSE, а FALSE в TRUE:

t1
## [1] TRUE
!t1
## [1] FALSE
!!t1 #Двойное отрицание!
## [1] TRUE

Еще есть логическое И (выдаст TRUE только в том случае если обе переменные TRUE):

t1 & t2
## [1] TRUE
t1 & f1
## [1] FALSE

А еще логическое ИЛИ (выдаст TRUE в случае если хотя бы одна из переменных TRUE):

t1 | f1
## [1] TRUE
f1 | f2
## [1] FALSE

Если кому-то вдруг понадобится другое ИЛИ (строгое ЛИБО) — есть функция xor(), принимающая два аргумента и возвращая TRUE только в том случае, если ровно один из двух аргументов равен TRUE.

Итак, мы только что разобрались с самой занудной (хотя и важной) частью - с основными типа данных в R и как с ними работать8. Пора переходить к чему-то более интересному и специфическому для R. Вперед к ВЕКТОРАМ!


  1. При первом запуске RStudio вы не увидите это окно. Для того, чтобы оно появилось, нужно нажать File - New File - R Script.↩︎

  2. В RStudio есть много удобных сочетаний горячих клавиш. Чтобы посмотреть их все, нажмите Help - Keyboard Shortcuts Help.↩︎

  3. Во время написания кода вам может казаться понятным то, что вы написали, но при возвращении к коду через некоторое время вы уже не будете этого помнить. Старайтесь писать комментарии как можно чаще!↩︎

  4. Stackoverflow — это сайт с вопросами и ответами. Эдакий аналог Quora, The Question, ну или Ответы Mail.ru в мире программирования.↩︎

  5. Есть еще оператор ->, который позволяет присваивать значения слева направо, но так делать не рекомендуется, хотя это бывает довольно удобным.↩︎

  6. Еще иногда используются большие буквы SomeVariable, но это плохо читается, а иногда — точка, но это тоже не рекомендуется.↩︎

  7. Комплексные числа в R пишутся так: complexnumber <- 2+2i. i здесь - это та самая мнимая единица, которая является квадратным корнем из -1.↩︎

  8. Кроме описанных пяти типов данных (integer, double, complex, character и logical) есть еще и шестой — это raw, сырая последовательность байтов, но нам она не понадобится.↩︎