Суммируя несколько столбцов с dplyr?

Я немного борюсь с dplyr-синтаксисом. У меня есть кадр данных с разными переменными и одна переменная группировки. Теперь я хочу рассчитать среднее значение для каждого столбца в каждой группе, используя dplyr в R.

df % group_by(grp) %>% summarise(mean(a)) 

Это дает мне значение для столбца «a» для каждой группы, обозначенной «grp».

Мой вопрос: возможно ли получить средства для каждого столбца в каждой группе одновременно? Или мне нужно повторить df %>% group_by(grp) %>% summarise(mean(a)) для каждого столбца?

То, что я хотел бы иметь, это что-то вроде

 df %>% group_by(grp) %>% summarise(mean(a:d)) # "mean(a:d)" does not work 

5 Solutions collect form web for “Суммируя несколько столбцов с dplyr?”

Для этой dplyr пакет dplyr содержит summarise_all :

 df %>% group_by(grp) %>% summarise_all(funs(mean)) #> Source: local data frame [3 x 5] #> #> grp abcd #> (int) (dbl) (dbl) (dbl) (dbl) #> 1 1 3.000000 2.666667 2.666667 3.333333 #> 2 2 2.666667 2.666667 2.500000 2.833333 #> 3 3 4.000000 1.000000 4.000000 3.000000 

Если вы хотите обобщить только определенные столбцы, используйте функции summarise_at или summarise_if .

В качестве purrrlyr пакет purrrlyr обеспечивает ту же функциональность:

 df %>% slice_rows("grp") %>% dmap(mean) #> Source: local data frame [3 x 5] #> #> grp abcd #> (int) (dbl) (dbl) (dbl) (dbl) #> 1 1 3.000000 2.666667 2.666667 3.333333 #> 2 2 2.666667 2.666667 2.500000 2.833333 #> 3 3 4.000000 1.000000 4.000000 3.000000 

Также не забывайте о data.table :

 setDT(df)[, lapply(.SD, mean), by = grp] #> grp abcd #> 1: 3 3.714286 3.714286 2.428571 2.428571 #> 2: 1 1.000000 4.000000 5.000000 2.000000 #> 3: 2 4.000000 4.500000 3.000000 3.000000 

Попробуем сравнить производительность.

 library(dplyr) library(purrrlyr) library(data.table) library(benchr) n < - 10000 df <- data.frame( a = sample(1:5, n, replace = TRUE), b = sample(1:5, n, replace = TRUE), c = sample(1:5, n, replace = TRUE), d = sample(1:5, n, replace = TRUE), grp = sample(1:3, n, replace = TRUE) ) dt <- setDT(df) benchmark( dplyr = df %>% group_by(grp) %>% summarise_all(funs(mean)), purrrlyr = df %>% slice_rows("grp") %>% dmap(mean), data.table = dt[, lapply(.SD, mean), by = grp] ) #> Benchmark summary: #> Time units : microseconds #> expr n.eval min lw.qu median mean up.qu max total relative #> dplyr 100 3490 3550 3710 3890 3780 15100 389000 6.98 #> purrrlyr 100 2540 2590 2680 2920 2860 12000 292000 5.04 #> data.table 100 459 500 531 563 571 1380 56300 1.00 

Мы можем суммировать, используя summarize_at , dplyr 0.7.4 и dplyr 0.7.4 по dplyr 0.7.4 . Мы можем установить несколько столбцов и функций, используя аргументы vars и vars ниже. Левая часть формулы funs присваивается суффиксу суммированных vars. В dplyr 0.7.4 summarise_eachmutate_each ) уже устарели, поэтому мы не можем использовать эти функции.

 options(scipen = 100, dplyr.width = Inf, dplyr.print_max = Inf) library(dplyr) packageVersion("dplyr") # [1] '0.7.4' set.seed(123) df < - data_frame( a = sample(1:5, 10, replace=T), b = sample(1:5, 10, replace=T), c = sample(1:5, 10, replace=T), d = sample(1:5, 10, replace=T), grp = as.character(sample(1:3, 10, replace=T)) # For convenience, specify character type ) df %>% group_by(grp) %>% summarise_each(.vars = letters[1:4], .funs = c(mean="mean")) # `summarise_each()` is deprecated. # Use `summarise_all()`, `summarise_at()` or `summarise_if()` instead. # To map `funs` over a selection of variables, use `summarise_at()` # Error: Strings must match column names. Unknown columns: mean 

Вы должны перейти к следующему коду. Следующие коды имеют одинаковый результат.

 # summarise_at df %>% group_by(grp) %>% summarise_at(.vars = letters[1:4], .funs = c(mean="mean")) df %>% group_by(grp) %>% summarise_at(.vars = names(.)[1:4], .funs = c(mean="mean")) df %>% group_by(grp) %>% summarise_at(.vars = vars(a,b,c,d), .funs = c(mean="mean")) # summarise_all df %>% group_by(grp) %>% summarise_all(.funs = c(mean="mean")) # summarise_if df %>% group_by(grp) %>% summarise_if(.predicate = function(x) is.numeric(x), .funs = funs(mean="mean")) # A tibble: 3 x 5 # grp a_mean b_mean c_mean d_mean #      # 1 1 2.80 3.00 3.6 3.00 # 2 2 4.25 2.75 4.0 3.75 # 3 3 3.00 5.00 1.0 2.00 

Вы также можете иметь несколько функций.

 df %>% group_by(grp) %>% summarise_at(.vars = letters[1:2], .funs = c(Mean="mean", Sd="sd")) # A tibble: 3 x 5 # grp a_Mean b_Mean a_Sd b_Sd #      # 1 1 2.80 3.00 1.4832397 1.870829 # 2 2 4.25 2.75 0.9574271 1.258306 # 3 3 3.00 5.00 NA NA 

Вы можете просто передать больше аргументов, чтобы summarise :

 df %>% group_by(grp) %>% summarise(mean(a), mean(b), mean(c), mean(d)) 

Источник: локальный фрейм данных [3 x 5]

  grp mean(a) mean(b) mean(c) mean(d) 1 1 2.500000 3.500000 2.000000 3.0 2 2 3.800000 3.200000 3.200000 2.8 3 3 3.666667 3.333333 2.333333 3.0 

Для полноты: с dplyr v0.2 ddply with colwise также сделает следующее:

 > ddply(df, .(grp), colwise(mean)) grp abcd 1 1 4.333333 4.00 1.000000 2.000000 2 2 2.000000 2.75 2.750000 2.750000 3 3 3.000000 4.00 4.333333 3.666667 

но он медленнее, по крайней мере в этом случае:

 > microbenchmark(ddply(df, .(grp), colwise(mean)), df %>% group_by(grp) %>% summarise_each(funs(mean))) Unit: milliseconds expr min lq mean ddply(df, .(grp), colwise(mean)) 3.278002 3.331744 3.533835 df %>% group_by(grp) %>% summarise_each(funs(mean)) 1.001789 1.031528 1.109337 median uq max neval 3.353633 3.378089 7.592209 100 1.121954 1.133428 2.292216 100 

Все примеры замечательные, но я полагаю, что добавлю еще одно, чтобы показать, как упрощается работа в «аккуратном» формате. Прямо сейчас кадр данных находится в «широком» формате, что означает, что переменные «a» через «d» представлены в столбцах. Чтобы добраться до «аккуратного» (или длинного) формата, вы можете использовать команду gather() из пакета tidyr , который перемещает переменные в столбцах «a» через «d» в строки. Затем вы используете функции group_by() и group_by() чтобы получить среднее значение для каждой группы. Если вы хотите представить данные в широком формате, просто примените дополнительный вызов функции spread() .

 library(tidyverse) # Create reproducible df set.seed(101) df < - tibble(a = sample(1:5, 10, replace=T), b = sample(1:5, 10, replace=T), c = sample(1:5, 10, replace=T), d = sample(1:5, 10, replace=T), grp = sample(1:3, 10, replace=T)) # Convert to tidy format using gather df %>% gather(key = variable, value = value, a:d) %>% group_by(grp, variable) %>% summarize(mean = mean(value)) %>% spread(variable, mean) #> Source: local data frame [3 x 5] #> Groups: grp [3] #> #> grp abcd #> *      #> 1 1 3.000000 3.5 3.250000 3.250000 #> 2 2 1.666667 4.0 4.666667 2.666667 #> 3 3 3.333333 3.0 2.333333 2.333333 
  • Создайте пустой файл data.frame
  • Как написать trycatch в R
  • Как связывать или переписывать векторы разных длин без повторения элементов более коротких векторов?
  • Эмулировать цветовую палитру по умолчанию ggplot2
  • Заменить бары в geom_bar ggplot2
  • Сделать фон графика разными цветами в разных регионах
  • Используйте другой центр, чем основной меридиан, при построении карты мира
  • Как сказать, что находится в одном векторе, а не в другом?
  • Динамически строить вызов для поиска нескольких столбцов
  • Причины использования функции set.seed
  • Удалите весь столбец из data.frame в R
  • Давайте будем гением компьютера.