R – это язык программирования для обработки и анализа данных, распространяющийся бесплатно и дополняющийся пользователями. Правила этого языка достаточно просты. Но чтобы не потеряться в R, нужно привыкнуть к основным понятиям. Давайте с ними познакомимся.
Работа в R строится на использовании функций. Но что такое функция? Функция – это маленькая программа, представляющая из себя последовательность простых (или не очень) операций, которые проводятся над каким-то объектом, который мы отдали функции на обработку. Этот объект называется аргументом. Например, есть функция, которая извлекает квадратный корень из некоторого числа. Число будет аргументом функции (совсем как в математике). Функция может иметь несколько аргументов, указывающих не только на то, с каким объектом нужно проводить операции, но и как их проводить.
Чтобы узнать, что делает та или иная функция, сколько у нее аргументов и за что они отвечают, можно воспользоваться подсказками, встроенными в R, прописав вопросительный знак перед названием функции:
?sqrt
Для того, чтобы пользоваться всеми – многогранными – возможностями R, вам потребуется обращаться к внешним пакетам. Пакет в R – это группа функций, объединенных выполнением схожих задач. Например, пакет foreign позволяет загружать в R файлы данных различных расширений (например, из файлы данных из пакетов SPSS или Stata) и сохранять данные в файлы с этими расширениями.
Для того, чтобы использовать пакет, сначала вам требуется скачать его и установить – как и любую другую программу на ваш компьютер, с тем отличием, что вы устанавливаете программу внутрь R. Это делается следующим образом – название пакета обязательно заключается в кавычки:
install.packages("foreign")
Обратите внимание, что если вы пользуетесь стационарными компьютерами в компьютерных классах, вам нужно устанавливать пакеты каждый раз, когда вы открываете R.
После того, как вы установили программу, вы захотите ее открыть. Также нужно открывать и пакеты в R перед их использованием каждый раз, когда вы запускаете R. Это делается так – теперь название пакета прописывается без кавычек:
library(foreign)
На Windows иногда возникает ошибка, когда R не может сохранить установочные файлы пакета на компьютер из-за того, что доступ к папке запрещен. В этом случае вам требуется открыть R от имени администратора (кликнув на иконку правой кнопкой мыши).
Чтобы открыть или сохранить файл с данными, вам нужно будет указывать полный путь к нему. Делать это каждый раз бывает неудобно. Для этого случая у R есть понятие рабочей директории: это папка, из которой R открывает файлы и в которую их сохраняет. Чтобы узнать, какая папка по дефолту используется R как рабочая директория, нужно воспользоваться функцией:
getwd()
Чтобы поменять рабочую директорию, нужно воспользоваться функцией setwd(), где в качестве аргумента нужно указать путь к нужной папке в кавычках.
setwd("C:/Users/student/Desktop/pr01")
Там не менее, вы можете открыть файл из любой папки и записать файл в любую папку, просто прописав полный путь к ней.
10+320
## [1] 330
10*320
## [1] 3200
Функция квадратного корня:
sqrt(3200)
## [1] 56.56854
Функция модуля:
abs(-16)
## [1] 16
В R существует и функция округления, которая нам может потребоваться для оформления аккуратных результатов расчетов. По дефолту R округляет до целого числа:
round(2/3)
## [1] 1
Можно указать, какое количество знаков после запятой мы хотим получить в результате. Для этого нужно прописать дополнительный аргумент внутри функции:
round(2/3, 4)
## [1] 0.6667
Обратите внимание, что в R, в отличие от Excel, целая часть от дробной отделяется точкой.
В ряде резлуьтатов в будущем нам будет встречаться так называемая экспоненциальная запись чисел. Она используется для удобного отображения очень больших или очень маленьких чисел через произведение \(a\times 10^b\), где a – любое число, по модулю не меньшее 1, но меньшее 10. Например, мы можем представить миллион как произведение \(1\times 10^6\).
Давайте посмотрим на очень большое число, возведя число 16 в степень 16:
16^16
## [1] 1.844674e+19
R обозначет умножение на 10 в некоторой степени как e.
Теперь очень маленькое число. Обратите внимание на знак после e:
1/16^16
## [1] 5.421011e-20
R можно использовать для подсчета вероятностей для различных распределений. Например, для нормального распределения мы можем рассчитать вероятность того, что случайная величина будет меньше или больше некоторого значения, не обращаясь к таблице стандартного нормального распределения.
Для этого используется функция pnorm(), имеющая три аргумента: q – значение (или значения) случайной величины, для которых мы ищем вероятности; mean – математическое ожидание; sd – стандартное отклонение; lower.tail – поиск вероятности \(P(X<x)\). По дефолту (то есть, если не прописывать иное) аргументы функции принимают следующие значения: pnorm(q, mean=0, sd=1, lower.tail=TRUE).
Рассчитаем \(F(1)=P(Z<1)\):
pnorm(1)
## [1] 0.8413447
Эта же функция позволяет рассчитать \(P(Z>1)\). Для этого нужно прописать аргумент lower.tail=FALSE, тем самым выбрав площадь под графиком функции плотности стандартного нормального распределения, которая рассматриваемого искомого значения.
pnorm(1, lower.tail = FALSE)
## [1] 0.1586553
Мы можем работать не только со стандартным нормальным распределением:
pnorm(5, mean=7, sd=3)
## [1] 0.2524925
Работа с R выстраивается через работу с объектами, в которые вы сохраняете результаты ваших вычислений или любую другую необходимую информацию, и к которым можете впоследствии обращаться. Удобство R заключается в том, что вы, например, можете работать одновременно с несколькими таблицами, полученными из различных источников (тогда как, чтобы открыть новый файл в Excel, вам требуется запустить новое окно программы).
Начнем с самых простых объектов, содержащих один элемент. Давайте сохраним в объект pr_left (от probability) вероятность того, что \(Z<1\). Чтобы это сделать, нужно воспользоваться оператором присваивания <-. Код читается так: нужно сохранить вероятность, рассчитанную функцией pnorm(), в объект pr_left.
pr_left <- pnorm(1)
Создадим еще один объект, куда запишем вероятность того, что \(Z>1\).
pr_right <- pnorm(1, lower.tail = FALSE)
Примечание. Названия объектов могут быть любыми (но не могут содержать пробелов), но традиционно они должны быть удобны в работе: короткими и отражающими содержание. Например, базы данных часто называют как df или data.
Что, если мы хотим сравнить эти два значения? Для этого в R существуют логические операторы ==, !=, >, <, >= (больше или равно), <= (меньше или равно). Эти операторы важно знать, чтобы в дальнейшем уметь проводить отбор наблюдений по некоторым условиям.
Результатом сравнений будет логические значения TRUE или FALSE:
pr_left == pr_right
## [1] FALSE
Действительно ли эти вероятности не равны?
pr_left != pr_right
## [1] TRUE
В R существуют несколько базовых типов данных:
TRUE или FALSE.Мы можем проверять, к какому типу данных относятся наши объекты:
is.numeric(pr_left)
## [1] TRUE
is.character(pr_left)
## [1] FALSE
is.logical(pr_left)
## [1] FALSE
Можно преобразовывать данные в другие типы. Например, мы можем сохранить число как текст (но не можем сохранить текст, как число):
as.character(pr_left)
## [1] "0.841344746068543"
Можно узнать тип объекта:
class(pr_left)
## [1] "numeric"
Вектором называется набор объектов, имеющих одинаковый тип. Векторы в R создаются через структуру c(). Создадим вектор имен некоторых героев сериала «Твин Пикс»:
damn_good_coffee <- c("Laura", "Harry", "Donna", "Dale", "Audrie")
Можно обращаться к различным элементам вектора. Для этого, вам нужно в квадратных скобках прописать номер элемента, который вы хотите вызвать:
damn_good_coffee[3]
## [1] "Donna"
Можно вызвать элементы, расположенные рядом. Например, мы хотим вызвать 2, 3 и 4 имя:
damn_good_coffee[2:4]
## [1] "Harry" "Donna" "Dale"
Можно вызвать элементы, не расположенные рядом. Тогда в квадратные скобки вам нужно записать вектор номеров элементов.
damn_good_coffee[c(1,5)]
## [1] "Laura" "Audrie"
Если вы забудете прописать вектор, R вас не поймет. Он подумает, что вы работаете с таблицей.
Функция lenght() считает количество элементов в векторе:
length(names)
## [1] 1
Часто мы хотим узнать номер элемента внутри вектора, зная его значение. Для этого существует функция which(), где аргумент vector == value нужно читать как «какой/-ие из элементов вектора vector принимают значение value?»:
which(damn_good_coffee == "Dale")
## [1] 4
Векторы могут быть и чаще всего будут числовыми. Создадим вектор, принимающий целые значения от 1 до 20:
pineapple <- c(1:20)
pineapple
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Над векторами можно производить математические операции, которые будут осуществляться поэлементно. Например, в строке ниже каждый из элементов вектора pineapple будет разделен на 10.
pineapple/10
## [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7
## [18] 1.8 1.9 2.0
Можно отбрать элементы вектора на основании некоторых условий. Например:
pineapple[pineapple>=15 & pineapple <=18]
## [1] 15 16 17 18
Вот так мы можем исключить элемент, равный 15, из вектора:
pineapple[pineapple!=15]
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
Можно заменять элементы векторов, записывая в них другие значения:
pineapple[10]
## [1] 10
pineapple[10] <- 1000000
С помощью функции replace() можно заменить сразу много элементов, удовлетворяющих некоторому условию. Если вам потребуется преобразованный вектор, не забудьте сохранить его в новый объект:
avocado <- replace(pineapple, # то, где заменяем
pineapple <= 8, # условие замены
-1) # на что заменяем
avocado
## [1] -1 -1 -1 -1 -1 -1 -1 -1
## [9] 9 1000000 11 12 13 14 15 16
## [17] 17 18 19 20
Другой способ произвести замену многих элементов, удовлетворяющих условию:
avocado[avocado > 9] = 1
avocado
## [1] -1 -1 -1 -1 -1 -1 -1 -1 9 1 1 1 1 1 1 1 1 1 1 1
Что такое база данных? Это таблица, где каждая из строк содержит описания одного и того же наблюдения: например, респондента, региона или страны. В столбцах в этой таблице содержатся переменные – список измерений одного и того же признака, собранного для всех наблюдений в базе данных: например, рост и возраст респондента, средняя зарплата в регионе или количество политических партий в стране.
На семинаре мы провели мини-исследование, в котором студенты ответили на несколько вопросов про их рост, баллы ЕГЭ по биологии и математике, любимый предмет в школе, а также оценили на глазок длину представленного отрезка и угол. Мы случайно отобрали 7 анкет и занесли полученные результаты в векторы ответов на один и тот же вопрос. Они потребуются нам, чтобы собрать нашу первую базу данных. Векторы будут соответствовать столбцам, а номера элементов в векторе – строкам.
Рост:
height <- c(170, 169, 164, 163, 171, 161, 169.5)
Балл ЕГЭ по математике. У нас было 2 пропущенных значения. Эти пропущенные значения нельзя просто выкидывать. Нужно закодировать, что ответ на вопрос не был дан, через NA.
math_score <- c(76, 67, NA, 74, 78, NA, 72)
Балл ЕГЭ по биологии.
bio_score <- c(90, 79, NA, 77, 88, 66, 87)
Любимый предмет. Респонденту нужно было выбрать один ответ из 5 предложенных вариантов:
В вектор вносим код ответа:
subject <- c(2, 2, 5, 4, 2, 4, 2)
Пол (1 – девушка, 2 – молодой человек):
sex <- c(1, 1, NA, 1, 1, 1, 1)
Длина предложенного отрезка:
length <- c(20, 40, 30, 25, 25, 20, 25)
Предложенный угол:
angle <- c(20, 30, 30, 30, 22.5, 30, 37.5)
Обратите внимание: для корректного создания таблицы вам нужно, чтобы длина всех векторов была одинаковая.
Создадим нашу первую базу данных, используя функцию data.frame(). В аргументе через запятую вы присваиваете через оператор = названию колонки в таблице соответствующий вектор. Названия вы можете выбрать любые.
banana <- data.frame(height=height,
math=math_score,
bio=bio_score,
subject=subject,
gender=sex,
length=length,
angle=angle)
banana
## height math bio subject gender length angle
## 1 170.0 76 90 2 1 20 20.0
## 2 169.0 67 79 2 1 40 30.0
## 3 164.0 NA NA 5 NA 30 30.0
## 4 163.0 74 77 4 1 25 30.0
## 5 171.0 78 88 2 1 25 22.5
## 6 161.0 NA 66 4 1 20 30.0
## 7 169.5 72 87 2 1 25 37.5
Чтобы посмотреть на получившуюся базу данных в отдельном окне, можно воспользоваться функцией View(). Обратите внимание, что функция пишется с заглавной буквы, а R чувствителен к регистру. Если вы напишете ее с маленькой буквы, R не поймет.
View(banana)
Один из важных навыков работы с данными – отбор наблюдений, удовлетворяющих некоторому условию. Например, среди всех ответов участников эксперимента вы хотите поработать только с ответами девушек. Отбор наблюдений производится с помощью команды subset(), где первым аргументом будет ваша таблица с данными, а вторым – требуемое условие.
subset(banana, height > 165)
## height math bio subject gender length angle
## 1 170.0 76 90 2 1 20 20.0
## 2 169.0 67 79 2 1 40 30.0
## 5 171.0 78 88 2 1 25 22.5
## 7 169.5 72 87 2 1 25 37.5
subset(banana, subject == 5)
## height math bio subject gender length angle
## 3 164 NA NA 5 NA 30 30
Можно задавать сложные условия, используя логическое и: & (студенты, чей рост больше 165 см, и указанная ими длина отрезка превышает 25 см).
subset(banana, height > 165 & length > 25)
## height math bio subject gender length angle
## 2 169 67 79 2 1 40 30
А можно логическое или: | (студенты, чей рост больше 165 см или студенты, чья указанная длина отрезка превышает 25 см).
subset(banana, height > 165 | length > 25)
## height math bio subject gender length angle
## 1 170.0 76 90 2 1 20 20.0
## 2 169.0 67 79 2 1 40 30.0
## 3 164.0 NA NA 5 NA 30 30.0
## 5 171.0 78 88 2 1 25 22.5
## 7 169.5 72 87 2 1 25 37.5
Вашу базу данных вы можете сохранить в новый файл, чтобы потом смочь к нему вернуться. Запишем файл в файл расширения .csv, который может быть открыть в Excel. Файл сохранится в ту папку, которую вы указали как рабочую директорию в начале занятия.
write.csv2(banana, "banana.csv")
Агент Купер доволен вашей работой и считает, что вы должны порадовать себя хорошим кофе и вишневым пирогом.