Как вы уже, наверное, убедились, базовый R умеет очень много, в том числе и для работы с данными. Однако какие-то операции все равно выполнить довольно непросто.
Возьмем, например, задачу агрегации: вам нужно посчитать средний рост супергероев отдельно для мужчин и для женщин (а еще и для NA, за компанию). Три группы еще ничего, а если бы их было 10, 50 или 200? В базовом R для этого есть специальная функция aggregate(), но она довольно неудобная.
Поэтому стали появляться пакеты, которые пытаются сделать агрегацию и другие непростые операции максимально безболезненными способами. Основных таких пакетов два: data.table и tidyverse. Это огромные пакеты, которые очень сильно изменяют работу в R, в том числе в плане стиля и используемой парадигмы. Тем не менее, в основе своей стоит все то, что мы прошли раньше.
9.1 Подход {data.table}
data.table – это распространенный пакет, который позволяет анализировать датафреймы максимально быстро и с помощью очень лаконичного кода.
Давайте импортируем наш набор данных про супергероев. Для этого воспользуемся функцией fread() из пакета data.table. Эта функция нам уже знакома как функция для импорта больших наборов данных Глава 6.7.
“f” в fread() означает “fast and friendly”: эта функция очень быстрая и довольно хорошо угадывает формат текстовой таблицы.
Warning in
fread("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/heroes_information.csv",
: na.strings[4]==" " consists only of whitespace, ignoring. Since
strip.white=TRUE (default), use na.strings="" to specify that any number of
spaces in a string column should be read as <NA>.
Функция fread() создает не просто датафрейм, а дататейбл (datatable):
heroes_dt
V1 name Gender Eye color Race Hair color
<int> <char> <char> <char> <char> <char>
1: 0 A-Bomb Male yellow Human No Hair
2: 1 Abe Sapien Male blue Icthyo Sapien No Hair
3: 2 Abin Sur Male blue Ungaran No Hair
4: 3 Abomination Male green Human / Radiation No Hair
5: 4 Abraxas Male blue Cosmic Entity Black
---
730: 729 Yellowjacket II Female blue Human Strawberry Blond
731: 730 Ymir Male white Frost Giant No Hair
732: 731 Yoda Male brown Yoda's species White
733: 732 Zatanna Female blue Human Black
734: 733 Zoom Male red <NA> Brown
Height Publisher Skin color Alignment Weight
<num> <char> <char> <char> <int>
1: 203.0 Marvel Comics <NA> good 441
2: 191.0 Dark Horse Comics blue good 65
3: 185.0 DC Comics red good 90
4: 203.0 Marvel Comics <NA> bad 441
5: NA Marvel Comics <NA> bad NA
---
730: 165.0 Marvel Comics <NA> good 52
731: 304.8 Marvel Comics white good NA
732: 66.0 George Lucas green good 17
733: 170.0 DC Comics <NA> good 57
734: 185.0 DC Comics <NA> bad 81
Дататейбл – это “улучшенный” датафрейм: с ним работают все те функции, которые мы применяли для датафрейма, специальные функции для дататейбла, а что-то работает немного по-другому по сравнению с датафреймом. Например, оператор [, т.е. квадратные скобки.
Давайте посмотрим по-внимательнее как это происходит на примере расчета среднего роста супергероев, группируя по полу:
heroes_dt[, mean(Height, na.rm =TRUE), by =Gender]
Уух! Выглядит монструозно, да? Зато как мы все сделали используя минимальное количество знаков. Заметьте, что здесь необычного для нас:
Не нужно прописывать heroes_dt$Alignment, поиск переменной будет начинаться с колонок дататейбла.
Там, где мы раньше выбирали колонки, мы еще и расчеты можем вести.
Внутри квадратных скобок появилась вторая запятая, т.е. третье поле, в котором мы прописали группировку.
Несколько операций прописываются путем соединения квадратных скобочек, код превращается в эдакий паровозик1.
И это не все отличия!
На сайте пакета {data.table} особенно уделяется вниманию скорости data.table, приводя в качестве доказательства бэнчмарк, где сравниваются по скорости различные инструменты для работы с данными. data.table почти на порядок обгоняет как dplyr, так и питоновский pandas – самый используемый пакет для анализа данных в Python.
Разработчики data.table делают особый акцент на “консервативности” пакета: у него нет никаких зависимостей (в этом плане пакет data.table обгоняет большинство российских экспатов в Тбилиси), ему достаточно очень старой версии R, функционирование пакета не будет ломаться из-за выкинутых устаревших функций. В общем, data.table очень суров и уважаем программистами. Он и не особо пытается понравиться рядовым пользователям. Зато освоив его, вы сможете творить магию: то, что с помощью базового R, tidyverse или Python будет выполняться очень долго (если выполнится вообще), data.table сможет сделать гораздо быстрее, иногда в десятки и сотни раз!
Очень сильно, не правда ли? Чем же может ответить tidyverse?
9.2 Подход tidyverse
Давайте посмотрим, как будет выглядеть решение тех же задач (отбор строк по условию, агрегация и сортировка) в tidyverse.
Не пугайтесь сообщений, все в порядке. Во-первых, пакет tidyverse – это не просто пакет, а “пакет с пакетами” (да-да, как у вас дома), который подключает сразу несколько других пакетов, которые составляют ядро tidyverse. Список и версии этих пакетов tidyverse выводит при подключении. Разные пакеты tidyverse мы очень детально разберем позже (Глава 10 ), а сейчас просто посмотрите, как это все выглядит.
heroes_tbl<-read_csv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/heroes_information.csv", na =c("NA", "-", "-99", " "))
Функция read_csv() (не путать с функцией из базового R – read.csv()!) возвращает тиббл – “улучшенный” датафрейм, примерно как это было с дататейблом.
heroes_tbl
# A tibble: 734 × 11
...1 name Gender `Eye color` Race `Hair color` Height Publisher
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <chr>
1 0 A-Bomb Male yellow Human No Hair 203 Marvel C…
2 1 Abe Sapien Male blue Icthyo … No Hair 191 Dark Hor…
3 2 Abin Sur Male blue Ungaran No Hair 185 DC Comics
4 3 Abomination Male green Human /… No Hair 203 Marvel C…
5 4 Abraxas Male blue Cosmic … Black NA Marvel C…
6 5 Absorbing Man Male blue Human No Hair 193 Marvel C…
7 6 Adam Monroe Male blue <NA> Blond NA NBC - He…
8 7 Adam Strange Male blue Human Blond 185 DC Comics
9 8 Agent 13 Female blue <NA> Blond 173 Marvel C…
10 9 Agent Bob Male brown Human Brown 178 Marvel C…
# ℹ 724 more rows
# ℹ 3 more variables: `Skin color` <chr>, Alignment <chr>, Weight <dbl>
# A tibble: 3 × 2
Gender mean_height
<chr> <dbl>
1 Male 189.
2 <NA> 180.
3 Female 175.
Очень сильно отличается от того, как мы работали раньше! Хотя в основе лежит все тот же R. Код, написанный в tidyverse, нарочито многословен (особенно по сравнению с data.table), каждая отдельная операция имеет свою функцию. Писать нужно больше, зато это гораздо легче: меньше нужно думать, какими хитрыми трюками сделать преобразование данных. Нужно просто разделить весь процесс преобразования данных на отдельные операции и последовательно прописать их. Код получается аккуратный и очень читаемый, даже для человека, который не знает tidyverse или даже R в целом. Даже этот новый оператор %>% выглядит довольно понятно: его можно прочитать как “затем”.
Заметьте, что tidyverse выводит очень подробные сообщения, которые даже выглядят очень красиво: со всякими иконками, красивым форматированием. Разработчики tidyverse работают над тем, чтобы делать свой интерфейс максимально понятным для пользователя: говорящие сами за себя названия функций, куча удобных фишек на все случаи жизни.
tidyverse постоянно обновляется, регулярно появляются новые функции, а старые функции заменяются на более удобные новые. И это не всегда плюс: обновив пакеты, установленные год назад, вы можете обнаружить, что старый код перестал работать! Мол, мы тут придумали, как сделать лучше, переписывайте код заново (или используйте старые версии пакетов).
Разработчики tidyverse, в целом, не стремится за высокой скоростью. Часто можно заметить, что новые функции работают довольно медленно. Но если у вас строчек меньше миллиона, то разницу в скорости с data.table вы едва ли заметите.
Команда разработчиков tidyverse работает на компанию Posit (бывшая RStudio). Поэтому в RStudio вы найдете несколько “шпаргалок” для tidyverse, но не для data.table. Они также активно активно работают над популяризацией tidyverse, стараясь сделать вход в него максимально комфортным, особенно для людей без опыта программирования. tidyverse команда открыто заявляет о своей политике diversity, некоторые члены этой команды – открытые представители гендерных и сексуальных меньшинств.
9.3 {data.table} vs tidyverse
Так что же лучше: data.table или tidyverse? Это один из самых частых споров в R-комьюнити. У обоих подходов есть плюсы, которые можно обсуждать вечно. Сегодня tidyverse выигрывает в популярности, особенно за пределами русскоязычного пространства.
В последнее время data.table и tidyverse все меньше противостоят друг другу и все больше взаимодополняют. Например, некоторые используют в качестве основного инструмента tidyverse, но при работе с данными побольше переключаются на data.table2. Кроме того, сами разработчики tidyverse пытаются приладить суперскоростной data.table в tidyverse: пакет dtplyr позволяет “переводить” код, написанный в tidyverse в код на data.table.
Таким образом, выбирая из tidyverse и data.table, начинать лучше с более удобного и популярного tidyverse, чем и займемся далее.
Это работает и в базовом R, но именно в data.table это очень частая конструкция.↩︎