dplyr
.Библиотека dplyr
- библиотека для удобной работы с базами данных. С ее помощью можно более быстро получать описание базы данных, сохранять полученные результаты и группировать данные по определенному признаку. Научиться работать с это библиотекой несложно, нужно только понять общую логику, познакомиться с особыми операторами и функциями, а также немного попрактиковаться.
Для начала установим библиотеку и обратимся к ней:
install.packages("dplyr")
library(dplyr)
Теперь мы готовы к работе. Загрузим таблицу, с которой мы работали на прошлом семинаре.
df <- read.csv("http://math-info.hse.ru/f/2018-19/comm-math/marketing.csv")
dplyr
и оператор %>%
Некоторые функции, встроенные в библиотеку, похожи на обычные функций, которые мы использовали на прошлом занятии. Например, функция select()
, которая позволяет выбрать интересующие нас столбцы в базе данных:
df_small <- dplyr::select(df, MarketID, Promotion, SalesInThousands)
#View(df_small)
Также с помощью select()
можем исключить некоторые столбцы, которые нас не интересуют, поставив перед вектором столбцов минус (так же, как и раньше!):
df_small2 <- dplyr::select(df, -c(Week, LocationID))
#View(df_small2)
Столбцы можно выбирать по названиям, если столбцы идут подряд:
df_small3 <- dplyr::select(df, AgeOfStore:Week) # с AgeOfStore по Week
#View(df_small3)
Если хотим отобрать интересующие нас наблюдения, нам потребуется другая функция - filter()
.
medium <- filter(df, MarketSize == "Medium") # фирмы среднего размера
Можем прописывать сложные условия, например, выберем фирмы среднего размера, которые находятся на рынке более 5 лет:
df2 <- filter(df, MarketSize == "Medium" & AgeOfStore > 5)
Казалось бы, зачем использовать библиотеку dplyr, если результаты пока несильно отличаются от того, что мы делали на прошлом занятии без всяких библиотек? На самом деле, смысл использовать ее есть. И сейчас мы переходим к самому интересному.
В библиотеке dplyr
есть особый оператор %>%
, который позволяет выполнять операции пошагово. Смысл этого оператора такой: возьми, то, что слева от %>%
и передай это на вход функции, стоящей справа от %>%
. Посмотрим на простом примере:
df %>% View
Взять базу df
и подать ее на вход функции View
. Как можно заметить, во View
уже нет ни скобок, ни названия базы, потому что они и не нужны – R и так знает, с чем ему работать.
Рассмотрим другой пример. Возьмем базу df
, сначала выберем столбцы MarketID
, Promotion
, и SalesInThousands
, а потом запросим несколько первых строк базы:
df %>% select(MarketID, Promotion, SalesInThousands) %>%
head %>% View
В библиотеке dplyr
есть несколько других интересных и полезных функций. Например, arrange()
– функция, которая сортирует базу данных в соответствии со значениями переменной (или переменных), расположенных по возрастанию (если переменная текстовая, то по алфавиту). Отсортируем базу по показателю SalesInThousands
и посмотрим на первые несколько строк:
df %>% arrange(SalesInThousands) %>% head
## MarketID MarketSize LocationID AgeOfStore Promotion Week
## 1 6 Medium 507 5 2 2
## 2 6 Medium 506 12 2 4
## 3 1 Medium 6 10 3 2
## 4 1 Medium 5 10 2 4
## 5 6 Medium 507 5 2 4
## 6 1 Medium 10 5 2 3
## SalesInThousands
## 1 17.34
## 2 19.26
## 3 22.18
## 4 23.35
## 5 23.44
## 6 23.93
Если нам нужно отсортировать строки по показателю в порядке убывания, то следует внутри arrange()
дописать функцию desc()
(сокращение от descending):
df %>% arrange(desc(SalesInThousands)) %>% head
## MarketID MarketSize LocationID AgeOfStore Promotion Week
## 1 3 Large 218 2 1 1
## 2 3 Large 220 3 1 3
## 3 3 Large 209 1 1 4
## 4 3 Large 208 1 3 1
## 5 3 Large 209 1 1 2
## 6 3 Large 216 4 3 1
## SalesInThousands
## 1 99.65
## 2 99.12
## 3 97.61
## 4 96.48
## 5 96.01
## 6 94.89
Другая полезная функция – mutate()
– используется для создания и добавлению в базу данных новой переменной. Создадим переменную log_sales
– натуральный логарифм числа продаж.
df %>% mutate(log_sales = log(SalesInThousands))
Если теперь мы посмотрим на базу df
привычным образом, нас будет ждать сюрприз:
View(df)
Переменной log_income
в базе нет! Почему? Дело в том, что когда мы проделываем что-то с базой с помощью dplyr
и не сохраняем результат, изменения в самой базе не происходят. Как сохранить изменения? Очень просто: как всегда, сохранить результат в переменную, в которой хранится база:
df <- df %>% mutate(log_sales = log(SalesInThousands))
#View(df)
Добавлять можно и более одной переменной за раз: достаточно перечислить их через запятую внутри mutate()
.
summarize()
, group_by()
и tally()
Сейчас речь пойдет, пожалуй, о самых полезных функциях dplyr
:)
При работе с данными мы часто сталкиваемся с тем, что нам нужно получить какую-то сводную информацию по переменным. Для этого существует функция summarise()
. Попробуем пока получить общее число строк в базе данных:
df %>% summarise(total = n())
## total
## 1 548
Функция n()
универсальна, она используется для подсчета элементов. К ней мы еще вернемся.
Теперь сделаем что-нибудь более интересное. Определим минимальное, максимальное и среднее значение числа продаж в этой базе.
df %>% summarise(avg_sales = mean(SalesInThousands),
min_sales = min(SalesInThousands),
max_sales = max(SalesInThousands))
## avg_sales min_sales max_sales
## 1 NA NA NA
Почему R не хочет ничего считать? Потому что в переменно age есть пропущенные значения! Как справиться с этой проблемой? Самое простое и очевидное – удалить NA
из базы. Но это необязательно. У многих функций в R, работающих с переменными, есть параметр na.rm
, который позволяет зафиксировать, исключать ли пропущенные значения (rm - remove) при подсчете или нет.
df %>% summarise(avg_sales = mean(SalesInThousands, na.rm = TRUE),
min_sales = min(SalesInThousands, na.rm = TRUE),
max_sales = max(SalesInThousands, na.rm = TRUE))
## avg_sales min_sales max_sales
## 1 53.46596 17.34 99.65
Часто необходимо получить сводную информацию не по всем наблюдениям в базе, а по определенной группе. Для этого сначала нужно сгруппировать данные, основываясь на значениях какой-нибудь переменной. Воспользуемся функцией group_by()
и посмотрим, сколько в базе фирм разных размеров:
df %>% group_by(MarketSize) %>% summarise(count = n())
## # A tibble: 4 x 2
## MarketSize count
## <fct> <int>
## 1 "" 1
## 2 Large 167
## 3 Medium 320
## 4 Small 60
Так как у одной фирмы не указан размер и значение не является полноценным пропущенным (NA
), вместо трех групп фирм мы получили четыре. Поправим:
df <- filter(df, MarketSize != "") # удалить строки с "" в MarketSize
df %>% group_by(MarketSize) %>% summarise(count = n())
## # A tibble: 3 x 2
## MarketSize count
## <fct> <int>
## 1 Large 167
## 2 Medium 320
## 3 Small 60
А теперь посмотрим на среднее число продаж разных типов фирм:
df %>% group_by(MarketSize) %>% summarise(avg_sales = mean(SalesInThousands, na.rm = TRUE))
## # A tibble: 3 x 2
## MarketSize avg_sales
## <fct> <dbl>
## 1 Large 70.0
## 2 Medium 44.0
## 3 Small 57.4
Число наблюдений можно посчитать и по-другому – с помощью функции tally()
:
df %>% group_by(MarketSize) %>% tally()
## # A tibble: 3 x 2
## MarketSize n
## <fct> <int>
## 1 Large 167
## 2 Medium 320
## 3 Small 60