ylab - title ggplot in r




dplyr로 여러 열 요약? (4)

나는 dplyr-syntax로 조금 어려움을 겪고있다. 다른 변수와 하나의 그룹화 변수가있는 데이터 프레임이 있습니다. 이제 R에서 dplyr을 사용하여 각 그룹 내의 각 열에 대한 평균을 계산하려고합니다.

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))

이렇게하면 "grp"로 표시된 각 그룹의 열 "a"에 대한 평균값을 얻을 수 있습니다.

내 질문은 : 각 그룹 내의 각 열에 대한 평균을 한 번에 가져올 수 있습니까? 또는 각 열에 대해 df %>% group_by(grp) %>% summarise(mean(a)) 를 반복해야합니까?

내가 갖고 싶습니다.

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

간단히 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

모든 예제가 훌륭하지만, "깔끔한"형식으로 작업하는 것이 일을 단순화하는 방법을 보여주기 위해 하나 더 추가 할 것입니다. 현재 데이터 프레임은 "와이드"형식으로되어있어 "a"에서 "d"까지의 변수가 열에 표시됩니다. "깔끔한"(또는 긴) 형식을 얻으려면 열 "a"에서 "d"까지의 변수를 행으로 이동시키는 tidyr 패키지에서 gather() 를 사용할 수 있습니다. 그런 다음 group_by()summarize() 함수를 사용하여 각 그룹의 평균을 구합니다. 데이터를 와이드 형식으로 표시하려면 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        a     b        c        d
#> * <int>    <dbl> <dbl>    <dbl>    <dbl>
#> 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

dplyr 0.7.4 에서 summarize_at , summarize_allsummarize_if 를 사용하여 summarize_at 할 수 있습니다. 다음 코드와 같이 varsfuns 인수를 사용하여 여러 열과 함수를 설정할 수 있습니다. funs 수식의 왼쪽은 요약 된 vars 접미사에 할당됩니다. dplyr 0.7.4 에서 summarise_each (및 mutate_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

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




aggregate