[Перевод] Агрегирующие функции в dplyr
summarise()
используется с агрегирующими функциями, которые принимают на вход вектор значений, а возвращают одно. Функция summarise_each()
предлагает другой подход к summarise()
с такими же результатами.
Цель этой статьи — сравнить поведение summarise()
и summarise_each()
, учитывая два фактора, которыми мы можем управлять:
1. Сколькими переменными оперировать
- 1А, одна переменная
- 1В, более одной переменной
2. Сколько функций применять к каждой переменной
- 2А, одна функция
- 2В, более одной функции
Получается четыре варианта:
- Вариант 1: применить одну функцию к одной переменной
- Вариант 2: применить много функций к одной переменной
- Вариант 3: применить одну функцию к многим переменным
- Вариант 4: применить много функций к многим переменным
Также проверим эти четыре случая с и без опции group_by()
.
Пакет данных mtcars
Для этой статьи мы используем хорошо известный пакет данных mtcars
.
Сначала мы преобразуем его в объект tbl_df
. Со стандартным объектом data.frame
ничего не произойдет, зато будет доступен гораздо лучший метод вывода.
Наконец, для того, чтобы было легко ориентироваться, выделим только четыре переменных, с которыми будем работать:
mtcars <- mtcars %>%
tbl_df() %>%
select(cyl , mpg, disp)
Вариант 1: применить одну функцию к одной переменной
В этом случае summarise()
выдаст простой результат:
# без группировки
mtcars %>%
summarise (mean_mpg = mean(mpg))
## Source: local data frame [1 x 1]
##
## mean_mpg
## (dbl)
## 1 20.09062
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise (mean_mpg = mean(mpg))
## Source: local data frame [3 x 2]
##
## cyl mean_mpg
## (dbl) (dbl)
## 1 4 26.66364
## 2 6 19.74286
## 3 8 15.10000
Можно было использовать и функцию summarise_each()
, но ее использование менее обоснованно с точки зрения понятности кода.
# без группировки
mtcars %>%
summarise_each (funs(mean) , mean_mpg = mpg)
## Source: local data frame [1 x 1]
##
## mean_mpg
## (dbl)
## 1 20.09062
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each (funs(mean) , mean_mpg = mpg)
## Source: local data frame [3 x 2]
##
## cyl mean_mpg
## (dbl) (dbl)
## 1 4 26.66364
## 2 6 19.74286
## 3 8 15.10000
Вариант 2: применить много функций к одной переменной
В этом случае можно применить обе функции, и summarise()
, и summarise_each()
.
У функции summarise()
более интуитивно понятный синтаксис:
# без группировки
mtcars %>%
summarise (min_mpg = min(mpg), max_mpg = max(mpg))
## Source: local data frame [1 x 2]
##
## min_mpg max_mpg
## (dbl) (dbl)
## 1 10.4 33.9
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise (min_mpg = min(mpg), max_mpg = max(mpg))
## Source: local data frame [3 x 3]
##
## cyl min_mpg max_mpg
## (dbl) (dbl) (dbl)
## 1 4 21.4 33.9
## 2 6 17.8 21.4
## 3 8 10.4 19.2
Можно просто задавать имена выходных переменных:
max_mpg = max(mpg)
Когда к одной переменной применяется много функций, summarise_each()
использует более компактный и аккуратный синтаксис:
# без группировки
mtcars %>%
summarise_each (funs(min, max), mpg)
## Source: local data frame [1 x 2]
##
## min max
## (dbl) (dbl)
## 1 10.4 33.9
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each (funs(min, max), mpg)
## Source: local data frame [3 x 3]
##
## cyl min max
## (dbl) (dbl) (dbl)
## 1 4 21.4 33.9
## 2 6 17.8 21.4
## 3 8 10.4 19.2
Имена выходных переменных задаются именами функций: min
и max
. В этом случае мы теряем имя переменной, к которой применяется функция. Если нужно что-то вроде min_mpg
и max_mpg
, нужно переименовать функции внутри funs()
:
# без группировки
mtcars %>%
summarise_each (funs(min_mpg = min, max_mpg = max), mpg)
## Source: local data frame [1 x 2]
##
## min_mpg max_mpg
## (dbl) (dbl)
## 1 10.4 33.9
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each (funs(min_mpg = min, max_mpg = max), mpg)
## Source: local data frame [3 x 3]
##
## cyl min_mpg max_mpg
## (dbl) (dbl) (dbl)
## 1 4 21.4 33.9
## 2 6 17.8 21.4
## 3 8 10.4 19.2
Вариант 3: применить одну функцию к многим переменным
Этот вариант очень похож на предыдущий. Можно использовать обе функции: и summarise()
, и summarise_each()
.
Функция summarise()
снова имеет более интуитивный синтаксис, и имена выходных переменных можно задавать в обычной простой форме:
max_mpg = max(mpg)
# без группировки
mtcars %>%
summarise(mean_mpg = mean(mpg), mean_disp = mean(disp))
## Source: local data frame [1 x 2]
##
## mean_mpg mean_disp
## (dbl) (dbl)
## 1 20.09062 230.7219
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise(mean_mpg = mean(mpg), mean_disp = mean(disp))
## Source: local data frame [3 x 3]
##
## cyl mean_mpg mean_disp
## (dbl) (dbl) (dbl)
## 1 4 26.66364 105.1364
## 2 6 19.74286 183.3143
## 3 8 15.10000 353.1000
Когда ко многим переменным применяется одна функция, summarise_each()
использует более компактный и аккуратный синтаксис:
# без группировки
mtcars %>%
summarise_each(funs(mean) , mpg, disp)
## Source: local data frame [1 x 2]
##
## mpg disp
## (dbl) (dbl)
## 1 20.09062 230.7219
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each (funs(mean), mpg, disp)
## Source: local data frame [3 x 3]
##
## cyl mpg disp
## (dbl) (dbl) (dbl)
## 1 4 26.66364 105.1364
## 2 6 19.74286 183.3143
## 3 8 15.10000 353.1000
Имена выходных переменных определяется именами переменных: mpg
и disp
. В этом случае мы теряем имя функции, примененной к переменным — mean()
. Вероятно, хотелось бы что-то вроде mean_mpg
и mean_disp
. Для того, чтобы этого достичь, нужно соответственно переименовать переменные, передающиеся в »…» внутри summarise_each()
:
# без группировки
mtcars %>%
summarise_each(funs(mean) , mean_mpg = mpg, mean_disp = disp)
## Source: local data frame [1 x 2]
##
## mean_mpg mean_disp
## (dbl) (dbl)
## 1 20.09062 230.7219
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each(funs(mean) , mean_mpg = mpg, mean_disp = disp)
## Source: local data frame [3 x 3]
##
## cyl mean_mpg mean_disp
## (dbl) (dbl) (dbl)
## 1 4 26.66364 105.1364
## 2 6 19.74286 183.3143
## 3 8 15.10000 353.1000
Вариант 4: применить много функций к многим переменным
Как и в предыдущих случаях, обе функции, и summarise()
, и summarise_each()
, имеют свои преимущества.
Функция summarise()
снова имеет более интуитивный синтаксис, и имена выходных переменных можно задавать в обычной простой форме:
max_mpg = max(mpg)
# без группировки
mtcars %>%
summarise(min_mpg = min(mpg) , min_disp = min(disp), max_mpg = max(mpg) , max_disp = max(disp))
## Source: local data frame [1 x 4]
##
## min_mpg min_disp max_mpg max_disp
## (dbl) (dbl) (dbl) (dbl)
## 1 10.4 71.1 33.9 472
# с одной группой
mtcars %>%
group_by(cyl) %>%
summarise(min_mpg = min(mpg) , min_disp = min(disp), max_mpg = max(mpg) , max_disp = max(disp))
## Source: local data frame [3 x 5]
##
## cyl min_mpg min_disp max_mpg max_disp
## (dbl) (dbl) (dbl) (dbl) (dbl)
## 1 4 21.4 71.1 33.9 146.7
## 2 6 17.8 145.0 21.4 258.0
## 3 8 10.4 275.8 19.2 472.0
Когда ко многим переменным применяется много функций, summarise_each()
использует более компактный и аккуратный синтаксис:
# без группировки
mtcars %>%
summarise_each(funs(min, max) , mpg, disp)
## Source: local data frame [1 x 4]
##
## mpg_min disp_min mpg_max disp_max
## (dbl) (dbl) (dbl) (dbl)
## 1 10.4 71.1 33.9 472
# с одной группой
mtcars %>%
group_by(cyl) %>%
summarise_each(funs(min, max) , mpg, disp)
## Source: local data frame [3 x 5]
##
## cyl mpg_min disp_min mpg_max disp_max
## (dbl) (dbl) (dbl) (dbl) (dbl)
## 1 4 21.4 71.1 33.9 146.7
## 2 6 17.8 145.0 21.4 258.0
## 3 8 10.4 275.8 19.2 472.0
Имена выходных переменных можно задать так: variable_function
, т.е. mpg_min
, disp_min
и т.д.
Обратное именование переменных, т.е. function_variable
, невозможно при вызове summarise_each()
. Это можно реализовать с помощью отдельной команды.
# без группировки
mtcars %>%
summarise_each(funs(min, max) , mpg, disp) %>%
setNames(c("min_mpg", "min_disp", "max_mpg", "max_disp"))
## Source: local data frame [1 x 4]
##
## min_mpg min_disp max_mpg max_disp
## (dbl) (dbl) (dbl) (dbl)
## 1 10.4 71.1 33.9 472
# с группировкой
mtcars %>%
group_by(cyl) %>%
summarise_each(funs(min, max) , mpg, disp) %>%
setNames(c("gear", "min_mpg", "min_disp", "max_mpg", "max_disp"))
## Source: local data frame [3 x 5]
##
## gear min_mpg min_disp max_mpg max_disp
## (dbl) (dbl) (dbl) (dbl) (dbl)
## 1 4 21.4 71.1 33.9 146.7
## 2 6 17.8 145.0 21.4 258.0
## 3 8 10.4 275.8 19.2 472.0
Выводы
При использовании функций, возвращающих результат единичной длины, есть два основных кандидата:
summarise()
summarise_each()
Функция summarise()
имеет более простой синтаксис, а функция summarise_each()
— более компактный.
Вследствие этого, summarise()
больше подходит для одной переменной единственной функции. Чем больше количество переменных или функций, тем более оправдано применение summarise_each()
.
У функции summarise_each()
свой способ именования выходных переменных:
Вариант 2: применить много функций к одной переменной
Имена выходных переменных определяются именами функций. В этом случае мы теряем имя переменной, к которой применяются функции.Вариант 3: применить одну функцию к многим переменным
Имена выходных переменных определяются именами переменных. В этом случае мы теряем имя функции, применяемой к переменным.Вариант 4: применить много функций к многим переменным
Имена выходных переменных определяются нотацией variable_function. Внутри вызова summarise_each()
другое именование невозможно.