Суммирование нескольких столбцов с помощью dplyr? [дубликат]
этот вопрос уже есть ответ здесь:
- агрегировать / суммировать несколько переменных в группе (например, sum, mean) 5 ответов
- может ли dplyr суммировать несколько переменных без перечисления каждой из них? [дубликат] 2 ответы
Я немного борюсь с dplyr-синтаксисом. У меня есть фрейм данных с разными переменными и одной переменной группировки. Теперь я хочу вычислить среднее значение для каждого столбца в каждой группе, используя dplyr в R.
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)
)
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 ответов:
The
dplyr
комплектацияsummarise_all
для этого:df %>% group_by(grp) %>% summarise_all(funs(mean)) #> Source: local data frame [3 x 5] #> #> grp a b c d #> (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
пакет предоставляет ту же функциональность:df %>% slice_rows("grp") %>% dmap(mean) #> Source: local data frame [3 x 5] #> #> grp a b c d #> (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 a b c d #> 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
,summarize_all
иsummarize_if
ondplyr 0.7.4
. Мы можем установить несколько столбцов и функций с помощьюvars
иfuns
аргумент, как показано ниже кода. Левая часть формулы funs присваивается суффиксу суммированных vars. Вdplyr 0.7.4
,summarise_each
(иmutate_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 # <chr> <dbl> <dbl> <dbl> <dbl> # 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 # <chr> <dbl> <dbl> <dbl> <dbl> # 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
Сcolwise
также будет делать это:> ddply(df, .(grp), colwise(mean)) grp a b c d 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()
иsummarize()
функции для получения среднего значения каждой группы. Если вы хотите представить данные в широком формате, просто прикрепите дополнительный вызов к