Агрегирующие функции в 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() другое именование невозможно.

ссылка на оригинал статьи https://habrahabr.ru/post/281747/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *