Menu

dplyr в R: filter, select, mutate, summarize — практическое введение

Что такое dplyr, как его установить и как шесть основных глаголов вместе с пайпом превращают запутанный код работы с данными в читаемые конвейеры.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Что такое dplyr

dplyr — самый популярный пакет R для манипуляции данными, «грамматика данных», построенная из горстки глаголов. Каждый глагол — это функция, которая принимает датафрейм, делает ровно одну работу (оставить часть строк, добавить столбец, посчитать сводку по группам) и возвращает новый датафрейм. Поскольку у каждого глагола одинаковая форма — датафрейм на входе, датафрейм на выходе, — они соединяются пайпом в конвейеры, которые читаются сверху вниз, как рецепт. dplyr — ядро tidyverse, семейства пакетов (tidyr, ggplot2, readr) с общим дизайном.

Всё, что делает dplyr, умеет и базовый R. Вот небольшой анализ на чистом базовом R — отфильтровать встроенные данные mtcars до 4-цилиндровых машин, вычислить новый столбец и усреднить его по числу передач. Этот код можно запустить:

Это работает, и это хороший R. Но обратите внимание, как история размазана по индексации скобками, присваиванию через $ и формуле. Версия того же анализа на dplyr:

library(dplyr)

mtcars |>
    filter(cyl == 4) |>
    mutate(kml = mpg * 0.425) |>
    group_by(gear) |>
    summarize(avg_kml = round(mean(kml), 1))

Четыре глагола, в том порядке, в каком вы объяснили бы их вслух. Эта читаемость — весь смысл dplyr, и на конвейере из двадцати шагов она решает всё.

Сниппеты dplyr на этой странице статичны, потому что этот редактор выполняет только базовый R — чтобы запустить их, установите dplyr на своей машине, как показано ниже.

Установка и загрузка

Установка один раз, затем загрузка в каждом скрипте, который его использует:

install.packages("dplyr")   # once, per machine
library(dplyr)              # every script

Установка install.packages("tidyverse") вместо этого подтянет dplyr вместе с родственными пакетами. При загрузке dplyr предупреждает, что маскирует stats::filter и stats::lag, — это нормально, а не ошибка.

Шесть основных глаголов

Каждый глагол принимает датафрейм первым аргументом, а имена столбцов — голыми, без кавычек и префиксов df$.

filter() оставляет строки, подходящие под условие:

mtcars |> filter(mpg > 25)
mtcars |> filter(cyl == 4, hp < 70)   # comma = AND

select() оставляет столбцы по имени, диапазону или хелперу:

mtcars |> select(mpg, cyl, hp)
mtcars |> select(mpg:hp)              # a range of adjacent columns
mtcars |> select(starts_with("d"))    # disp, drat

mutate() добавляет или преобразует столбцы:

mtcars |> mutate(kml = mpg * 0.425, heavy = wt > 3.5)

arrange() сортирует строки — оберните столбец в desc() для сортировки по убыванию:

mtcars |> arrange(desc(mpg))

summarize() схлопывает строки в одну сводную строку, а group_by() заставляет его схлопывать по группам:

mtcars |>
    group_by(cyl) |>
    summarize(n = n(), avg_mpg = mean(mpg))

Сам по себе group_by() не делает ничего видимого — он лишь помечает датафрейм, чтобы следующий summarize() (или mutate()) работал группа за группой. У каждого глагола есть подробная статья в этой главе: фильтрация строк, добавление столбцов, сортировка и сводки по группам.

Соединение глаголов пайпом

Пайп |> берёт значение слева и передаёт его первым аргументом в функцию справа — x |> f(y) означает f(x, y). Поскольку каждый глагол dplyr принимает и возвращает датафрейм, глаголы можно сцеплять бесконечно:

mtcars |>
    filter(hp > 100) |>
    mutate(kml = mpg * 0.425) |>
    group_by(cyl) |>
    summarize(cars = n(), avg_kml = round(mean(kml), 1)) |>
    arrange(desc(avg_kml))

Прочитайте вслух: взять mtcars, оставить машины мощнее 100 лошадиных сил, добавить столбец километров на литр, сгруппировать по цилиндрам, посчитать и усреднить каждую группу, отсортировать по среднему. Ни промежуточных переменных, ни вложенности. В старом коде вместо |> используется %>% из пакета magrittr — для работы с dplyr они взаимозаменяемы, а |> (встроенный в R 4.1+) разобран в статье про пайпы.

count() и n(): помощники для подсчёта

Подсчёт настолько частая задача, что в dplyr для него есть сокращения. n() возвращает число строк в текущей группе (работает только внутри summarize() или mutate()), а count() сворачивает всю связку group_by() + summarize(n = n()) в один вызов:

mtcars |> count(cyl)                    # rows per cyl value
mtcars |> count(cyl, gear, sort = TRUE) # two groupers, biggest first

Если вы поймали себя на том, что пишете group_by(x) |> summarize(n = n()), замените это на count(x).

Замечание о тибблах

Глаголы dplyr часто возвращают тиббл — вариант датафрейма из tidyverse. Это и есть датафрейм (всё, что принимает датафрейм, принимает и тиббл), но с более дружелюбной печатью: только первые 10 строк, только помещающиеся столбцы, с типами под каждым именем. Два отличия, о которых стоит знать: тибблы никогда не используют имена строк (поэтому mtcars |> as_tibble() теряет названия машин — tidyverse ожидает, что идентификаторы живут в настоящем столбце), а индексация одинарными скобками всегда возвращает тиббл, а не иногда сваливается в вектор. Ни то ни другое не должно удивлять вас в повседневной работе; просто не пугайтесь, когда str() покажет tbl_df.

Что вы уносите с собой

  • dplyr — это грамматика: шесть глаголов, каждый делает одну работу над датафреймом, сцепляются пайпом.
  • filter() выбирает строки, select() — столбцы, mutate() добавляет столбцы, arrange() сортирует, group_by() + summarize() агрегирует.
  • x |> f(y) — это f(x, y): конвейеры читаются сверху вниз в порядке происходящего.
  • count() и n() закрывают большинство задач подсчёта.
  • Базовый R умеет всё то же; dplyr выигрывает в читаемости, когда конвейеры растут.

Дальше: фильтрация и выборка подробно — идиомы скобок базового R и место filter() из dplyr.

Часто задаваемые вопросы

Что такое dplyr в R?

dplyr — самый популярный пакет R для работы с датафреймами. Он даёт небольшой набор глаголов — filter(), select(), mutate(), arrange(), summarize(), group_by(), — каждый из которых делает одну операцию над датафреймом, и они соединяются пайпом в читаемые конвейеры. dplyr входит в tidyverse.

Как установить dplyr?

Выполните install.packages("dplyr") один раз, а затем пишите library(dplyr) в начале каждого скрипта, который его использует. Если вместо этого установить tidyverse, вы получите dplyr вместе с родственными пакетами (tidyr, ggplot2, readr) за один раз.

Нужен ли мне dplyr, или достаточно базового R?

Базовый R умеет всё то же, что и dplyr, — выборку по индексам, aggregate(), order(), — и знать его стоит, потому что он работает везде и без зависимостей. dplyr окупает установку, когда конвейеры становятся длинными: пять сцепленных глаголов читаются как предложение, тогда как базовый эквивалент — как головоломка из вложенных скобок.

В чём разница между summarize и summarise в dplyr?

Ни в чём. Это одна и та же функция в американском и британском написании; dplyr экспортирует обе. Используйте то написание, которое принято в вашей команде, и будьте последовательны.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ