![](https://habrastorage.org/getpro/habr/upload_files/66c/503/c0d/66c503c0df1e737c00c620513d71d804.jpeg)
Сегодня, 4 мая, в день Звездных войн мы подготовили для Вас подробный гайд по основным функциям библиотеки dplyr
. Почему именно в день Звездных войн? А потому что разбирать мы все будем на примере датасета starwars
.
Ну что, начнем!
Если Вы хотите получать еще больше интересных материалов по программированию, Data Science и математике, то подписывайтесь на нашу группу ВК, канал в Телеграме и Инстаграм. Каждый день мы публикуем полезный контент и вопросы с реальных собеседований.
Кстати говоря, а Вы знаете, почему день Звездных войн отмечается именно 4 мая? Все очень просто - знаменитая фраза «May the fource be with you» крайне созвучна с «May, the 4th», т.е. 4 мая.
Знакомство с датасетом
Для начала, давайте подключим библиотеку dplyr
. Делается это с помощью функции library
.
![](https://habrastorage.org/getpro/habr/upload_files/fce/cc6/2fe/fcecc62fe61d5fde7150966a887a208c.png)
Вместе с этой библиотекой нам становится доступен и датасет starwars
. Давайте выведем первые несколько строк на экран и посмотрим, какую информацию он в себе хранит.
![](https://habrastorage.org/getpro/habr/upload_files/a6a/d5c/7c0/a6ad5c7c0352455c55b653008a32502f.png)
name - имя или прозвище героя вселенной Звездных войн. Например, Оби-Ван Кеноби.
height - высота персонажа
mass - масса персонажа
hair_color - цвет волос
skin_color - цвет кожи
eye_color - цвет глаз
birth_year - год рождения (до битвы на Явине)
sex - биологический пол (есть существа без пола и гермафродиты)
gender - поведенческий пол персонажа (например, на какой пол запрограммированы дроиды)
homeworld - откуда существо
species - биологический вид
films - список фильмов, в которых появилось существо
vehicles - список транспорта, которым существо управляло
starships - список космических кораблей, которыми существо управляло
В принципе, все предельно понятно, поэтому можем переходить к знакомству с dplyr
и обработке нашего датасета. Дадим полет нашей фантазии и немного покрутим-повертим наши данные.
Знакомство с dplyr
dplyr
- это один из основных пакетов семейства tidyverse
. Его ближайший аналог в Python
- библиотека Pandas
. Библиотека dplyr
служит для манипуляции с данными: фильтрация, сортировка, создание вычислимых столбцов и так далее.
По своему функционалу библиотека
dplyr
очень похожа на стандартный синтаксисSQL
. Немного ранее мы вместе с Алексеем Селезневым из Netpeak делали карточки: сравнение глаголовdplyr
и операторовSQL
. Вы можете посмотреть их здесь.
Перед тем, как переходить к рассмотрению глаголов библиотеки dplyr
, нужно упомянуть, что все пакеты tidyverse
основаны на концепции tidy data
. Если коротко, то «аккуратные данные» - это способ организации датафреймов по трем основным постулатам:
Каждая переменная находится в отдельном столбце
Каждое измерение находится в отдельной строке
Каждое значение находится в отдельной ячейке
![](https://habrastorage.org/getpro/habr/upload_files/b04/e53/032/b04e53032e0226cfd2a4b3f9de81c099.jpg)
Кстати говоря, наш датасет starwars
не совсем соответствует этим правилам. Нам это не помешает, но сможете ли Вы найти, в чем именно несоответствие?
Если Вы хотите поподробней познакомиться с
tidy data
, рекомендуем нашу статью.
Итак, вернемся к глаголам dplyr
. Пакет dplyr
позволяет делать несколько основных операций:
Отбор столбцов
Фильтрация строк
Сортировка строк
Группировка
Агрегирование
Создание вычислимых столбцов
Объединение таблиц
Давайте переходить к практике - хватит теории!
![](https://habrastorage.org/getpro/habr/upload_files/f69/b28/2c3/f69b282c3e805d0ad0a92e38f93aa1f4.jpg)
Отбор столбцов
Давайте начнем с самого простого - как выбрать только определенные столбцы из таблицы? Очень просто - с помощью функции select
.
![](https://habrastorage.org/getpro/habr/upload_files/94a/2ba/d33/94a2bad33cf2d1cc48fa09c1ce42c5de.png)
А что если нам проще указать, какие столбцы не надо отбирать? Например, в таблице 20 столбцов, а нам нужно исключить только первый столбец. Или столбец с определенными названиями. Не проблема - просто добавьте знак минус:
![](https://habrastorage.org/getpro/habr/upload_files/d6b/1c5/06c/d6b1c506cefc509990d1ceb7ec2c8842.png)
Но и это не все возможности функции select
. Мы можем воспользоваться вспомогательными функциями, чтобы кастомизировать отбор столбцов. Вот список этих функций:
contains
: название столбца содержитends_with
: название столбца заканчивается наmatches
: название столбца соответствует регулярному выражениюnum_range
: поиск занумерованных столбцов, например, «V1, V2, V3...»one_of
: название столбца соответствует одному из вариантовstarts_with
: название столбца начинается с
Давайте рассмотрим несколько примеров. Для начала отберем столбцы, название которых содержит букву «а»
.
![](https://habrastorage.org/getpro/habr/upload_files/7be/811/137/7be811137dd07f29694ff701bd4678a8.png)
Теперь отберем столбцы, название которых является одним из указанных.
![](https://habrastorage.org/getpro/habr/upload_files/ab8/0bb/634/ab80bb6343495a9b5867e68789230c3f.png)
И в заключение - поиск по регулярному выражению: отбираем столбцы, в названии которых буква «t»
стоит на любом месте, но после нее обязательно идет хотя бы 1 символ.
![](https://habrastorage.org/getpro/habr/upload_files/58e/649/5cf/58e6495cfaa619524c1ec7d1df311574.png)
Обратите внимание, все наши запросы возвращали таблицу tibble
. А что, если мы хотим отобрать столбец и сразу начать работать с ним, как с вектором? Мало кто знает, но для этого в dplyr
есть специальная функция pull
. Она возвращает не таблицу, как остальные глаголы dplyr
, а вектор.
![](https://habrastorage.org/getpro/habr/upload_files/86f/bbd/152/86fbbd1525b5342a156a5032a21b1121.png)
В целом, это весь основной функционал для отбора столбцов. Едва ли Вы не сможете найти решение своей задачи с помощью этих функций, так что мы переходим дальше.
Фильтрация строк
Фильтрация строк по значениям - это аналог привычного оператора WHERE
в SQL
. В синтаксисе dplyr
же для этого используется глагол filter
(как неожиданно, правда?).
Использовать filter
очень просто - задаем некое логическое выражение и функция вернет только те строки, для которых это выражение True
. Например:
![](https://habrastorage.org/getpro/habr/upload_files/e26/641/099/e26641099489f42341775fde1944ba61.png)
Вы можете комбинировать несколько условий с помощью &
и |
:
![](https://habrastorage.org/getpro/habr/upload_files/d09/051/661/d090516614ddf78359dee7c65b19caad.png)
Логические выражения Вы можете конструировать не только с помощью >/<
, но и с помощью других логических операторов:
>=
<=
is.na
!is.na
%in%
!
Например:
![](https://habrastorage.org/getpro/habr/upload_files/515/377/47f/51537747fe0c162a412e62a0d71eb64d.png)
Помимо функции filter
, отбирать строки можно и с помощью других глаголов. Например, функция distinct
позволяет исключить дублирующиеся значения в определенном столбце.
![](https://habrastorage.org/getpro/habr/upload_files/237/497/a23/237497a23aa8f83badba8257444e25fe.png)
Другая функция, sample_n
, отбирает n
случайных строк.
![](https://habrastorage.org/getpro/habr/upload_files/acc/f2e/303/accf2e30368a75e31578cf63ced8354e.png)
Функция slice
же, например, позволяет отбирать строки по их индексу:
![](https://habrastorage.org/getpro/habr/upload_files/476/f5e/58b/476f5e58baf492c534e7397c9e6828d5.png)
Функция sample_frac
делает случайную подвыборку из таблицы. Нужно указать долю строк из общего числа, которые должны быть в итоговой таблице. Например, при параметре 0.5
вернется половина строк из таблицы, выбранные случайным образом.
![](https://habrastorage.org/getpro/habr/upload_files/d73/b49/390/d73b49390872dfb4135b56d005adbfef.png)
Итак, с фильтрацией строк мы тоже разобрались, переходим к следующему разделу.
Сортировка строк
За сортировку строк в SQL
отвечает оператор ORDER BY
. В dplyr
для этого существует функция arrange
.
Синтаксис максимально прост - достаточно указать столбец, по которому выполняется сортировка.
![](https://habrastorage.org/getpro/habr/upload_files/1cf/874/8f6/1cf8748f6e9fdfdd0babf3eacde74a73.png)
Чтобы отсортировать строки по убыванию, достаточно добавить функцию desc
.
![](https://habrastorage.org/getpro/habr/upload_files/139/087/02e/13908702ed1eba1239dad084d2204405.png)
А если отсортировать нужно по нескольким столбцам? Легко, просто указываем их названия :)
![](https://habrastorage.org/getpro/habr/upload_files/4b3/535/f45/4b3535f453b8a293a628595bbdddbb35.png)
Кстати говоря, с arrange
Вы можете также использовать вспомогательные глаголы, которые мы обсуждали в блоке с select
. Для этого нужно использовать функцию across
. Например:
![](https://habrastorage.org/getpro/habr/upload_files/95c/352/68f/95c35268f8ffe74131d86d6114b89efa.png)
Про сортировку, пожалуй, сказать больше нечего - переходим к группировкам.
Группировка и агрегатные функции
Группировка - базовая операция, которая необходима для расчета различных характеристик - средних значений, медиан, сумм, количества строк в группе и так далее. В SQL
для этого используется оператор GROUP BY
и агрегатные функции sum, min, max
и так далее. В dplyr
же… все то же самое. Ну, почти.
Давайте для начала сгруппируем наши строки по полю eye_color
:
![](https://habrastorage.org/getpro/habr/upload_files/592/654/e91/592654e91c9db5f50aec8640c629449b.png)
Мы получили сгруппированную таблицу из 15 групп, но внешне пока ничего не изменилось. В группировке как таковой смысла особо нет - нужно произвести какой-нибудь расчет. Для этого используется функция summarise
и соответствующие агрегатные функции.
Давайте посчитаем для каждой группы среднюю массу, максимальную массу, минимальную массу, медианную массу, самую первую массу в группе и количество элементов в каждой группе.
![](https://habrastorage.org/getpro/habr/upload_files/5b5/3e7/e65/5b53e7e65b60c1a2e5d69b9b71d05c72.png)
Обратите внимание, здесь мы дополнительно воспользовались функцией drop_na
из пакета tidyr
, чтобы удалить строки, в которых есть пропуски. Сделали мы это, чтобы при расчете наших максимальных/минимальных/других агрегатных значений не вылезали значения NA
.
На выходе мы получили 4 группы (во всех остальных были пропуски, по всей видимости) и рассчитанные для них характеристики. Также каждому столбцу присвоено то имя, которое мы дали ему в функции summarise
.
Мы с Вами здесь использовали только несколько агрегатных функций, но вообще говоря, их больше:
n_distinct
- считает количество уникальных элементов в группеlast
- возвращает последнее значение в группеnth
- возвращает n-ое значение из группыquantile
- возвращает заданную квантильIQR
- межквартильный размах, inter-quartile rangemad
- медианное абсолютное отклонение, median absolute deviationsd
- стандартное отклонениеvar
- вариация
Хорошо, с базовой группировкой мы разобрались. А что если пойти дальше…
Продвинутая группировка
А как Вам такая задача - рассчитать все те же самые характеристики, что и в прошлый раз, но сразу для нескольких столбцов? Например, мы делали для mass
, а теперь давайте сделаем для mass
и height
.
Без проблем - достаточно применить уже известную функцию across
.
![](https://habrastorage.org/getpro/habr/upload_files/858/5d5/603/8585d56031eb7ec6833968c332a71a6a.png)
Видно, что характеристики рассчитались по полю mass
и height
для каждой группы в отдельности. Если не устраивает название столбцов, которое система дала по умолчанию («столбец_характеристики»), то можно менять шаблон с помощью параметра .names
.
Итак, на этом закончим раздел группировки и перейдем к вычислимым столбцам.
Вычислимые столбцы
Создание вычислимого столбца - стандартная задача. Например, есть столбец A
, столбец B
, а мы хотим вывести столбец A/B
. Или другой вариант - мы хотим проранжировать строки нашей таблицы. Все это можно сделать с помощью функции mutate.
Для начала базовая вещь - создадим вычислимый столбец отношения веса к росту.
![](https://habrastorage.org/getpro/habr/upload_files/ef4/2d9/8e2/ef42d98e24d11939281f3e2705bf0c63.png)
А если нам нужно применить одну и ту же функцию к нескольким столбцам? Без проблем - снова нас выручит across
. Например, давайте умножим на 10 все столбцы с численным типом данных. При этом мы не будем создавать новые столбцы - мы модифицируем старые.
![](https://habrastorage.org/getpro/habr/upload_files/355/284/a55/355284a5561d75f1d284e918eff7265b.png)
Видно, что в столбцах с весом, ростом и возрастом все значения умножились на 10.
Давайте и с текстом немного поработаем - ко всем строковым значениям добавим суффикс «_new»
. Для этого нам понадобится библиотека stringr
все из того же семейства tidyverse
.
![](https://habrastorage.org/getpro/habr/upload_files/f29/441/fb3/f29441fb30b48324d65d7a2ac40d50dc.png)
Хорошо видно, что ко всем строковым значениям добавился суффикс _new
. Таким же образом можно работать и с датой, со временем и с любым другим типом данных.
Помимо всего прочего, mutate
позволяет реализовать аналог оконных функций в SQL
. Например, давайте проранжируем строки без разрывов по полю mass
с помощью функции dense_rank
:
![](https://habrastorage.org/getpro/habr/upload_files/50c/706/ec1/50c706ec15ebe9ddf5067725757ece3a.png)
Видно, что в конец таблицы добавился новый столбец rnk
с рангами для каждой строки.
Таких функций, на самом деле, масса. Вот некоторые из них:
lag
lead
cumsum
dense_rank
ntile
row_number
case_when
coalesce
Это, пожалуй, самые популярные и все они на 100% перекликаются с SQL
. Приведем несколько примеров.
![](https://habrastorage.org/getpro/habr/upload_files/e94/58f/770/e9458f77080e384519a71c3313d27e54.png)
Ну что, давайте переходить к последнему пункту - к объединению таблиц.
Объединение таблиц
Пожалуй, последняя необходимая для полноценной работы с датафреймами операция - объединение таблиц. Операция объединения в dplyr
тесно связана с джоинами в SQL
. Вот перечень основных функций:
left_join
right_join
inner_join
full_join
Аналогичные глаголы присутствуют и в стандартном SQL
. Давайте создадим новую таблицу - возьмем датасет starwars
и оставим только те строки, где вид существа - человек. А после попробуем различные виды джоинов.
![](https://habrastorage.org/getpro/habr/upload_files/08f/6cc/00a/08f6cc00a9c27d4b325ad97343162be3.png)
Обратите внимание, мы воспользовались функцией rename и переименовали поле name. Сделали мы это намеренно, чтобы показать работу аргумента
by
(аналогON
вSQL
) для связи столбцов при джоине.
Делаем inner_join
, на выходе получаем только 35 строк, т.к. в таблице df
строк именно 35. Аргумент by
позволил нам указать, через какие столбцы таблицы связаны между собой.
Если сделать full_join
аналогичным образом, то строк в итоговой таблице будет 87, т.к. в таблице starwars
их 87.
Внимательный читатель может заметить, что при джоине одни и те же столбцы продублировались из двух таблиц. Т.е. столбец
mass
, например, в итоговой таблице фигурирует с суффиксом.x
и.y
. Как от этого избавиться?
1 вариант:
Если название столбцов позволяет, то Вы можете убрать аргумент by
из джоина. Тогда соединяться таблицы будут по всем столбцам, у которых совпадает названием. В нашем случае этот вариант подходит - названия одинаковые и в результат добавится только один столбец - new_name
.
![](https://habrastorage.org/getpro/habr/upload_files/923/f6a/d76/923f6ad763e3fa01787049bc200b58cf.png)
2 вариант:
В реальной жизни, к сожалению, все не так сказочно, поэтому можно сделать небольшую предварительную обработку и джойнить не всю таблицу, а только нужные столбцы. Например, так:
![](https://habrastorage.org/getpro/habr/upload_files/089/580/12e/08958012eccb79fbfd1c1fc52d575c32.png)
Помимо различных джоинов, в dplyr
есть еще другие функции для соединения таблиц:
bind_rows
- помещает одну таблицу «под» другойbind_cols
- ставит одну таблицу «справа» от другойintersect
- находит пересекающиеся строкиsetdiff
- разность таблиц, т.е. строки из первой таблицы, которых нет во второйunion
- возвращает строки, которые есть в любой из таблиц (дубликаты исключаются)union_all
- аналогичноunion
, но оставляет дуликаты
Эпилог
Мы с Вами рассмотрели все основные операции библиотеки dplyr
и почти все основные функции. Все остальное - практика, практика и еще раз практика. Если у Вас будут вопросы - рады будем помочь и ответить в комментариях :)
Если Вы хотите получать еще больше интересных материалов по программированию, Data Science и математике, то подписывайтесь на нашу группу ВК, канал в Телеграме и Инстаграм. Каждый день мы публикуем полезный контент и вопросы с реальных собеседований.
А, и совсем забыли. May the force be with you!
P.S. Здесь Вы можете найти официальную шпаргалку по всем функциям dplyr
. Все удобно и компактно собрано в одном месте :)