如何使用group_by()/ summarise()快速创建多个汇总表?

时间:2018-08-13 22:38:01

标签: r dplyr

我有一个数据帧,其中包含N个变量,M个分类和2个数字。我想创建M个数据帧,每个分类变量一个。

例如,

data %>%
group_by(var1) %>%
summarise(sumVar5 = sum(var5),
meanVar6 = mean(var6))

data %>%
group_by(varM) %>%
summarise(sumVar5 = sum(var5),
meanVar6 = mean(var6))

等...

有没有办法遍历分类变量并生成每个汇总表?即,不需要重复上述块M次。

或者,这些汇总表不必是单独的对象,只要我可以轻松地引用/提取M个变量中每个变量的汇总即可。

2 个答案:

答案 0 :(得分:1)

您没有提供示例数据集。因此,我创建了一个小示例来演示其工作原理。

data <- data_frame(var1 = rep(letters[1:5], 2),
                   var2 = rep(LETTERS[11:15], 2),
                   var3 = 1:10,
                   var4 = 11:20)

tidyverse软件包的组合可以使您到达需要的位置。 使用的步骤:首先,我们将所有要分组的列收集在cols列中,并将数字变量分开。接下来,我们将data.frame拆分为data.frames的列表,以便我们要分组的每一列都有自己的带有2个数字变量的表。现在所有内容都在列表中,我们需要使用purrr包中的map功能。使用map,我们再次分布data.frame,因此列名与我们期望的一样。最后,使用地图,我们使用group_by_if对字符列进行分组,并对其余部分进行汇总。所有结果都存储在列表中,您可以在其中访问所需的内容。

分段运行代码以查看每个步骤的作用。

library(dplyr)
library(purrr)
library(tidyr)

outcomes <- data %>% 
  gather(cols, value, -c(var3, var4)) %>% 
  split(.$cols) %>%
  map(~ spread(.x, cols, value)) %>% 
  map(~ group_by_if(.x, is.character) %>% 
        summarise(sumvar3 = sum(var3),
                  meanvar4 = mean(var4)))

outcomes

$`var1`
# A tibble: 5 x 3
  var1  sumvar3 meanvar4
  <chr>   <int>    <dbl>
1 a           7     13.5
2 b           9     14.5
3 c          11     15.5
4 d          13     16.5
5 e          15     17.5

$var2
# A tibble: 5 x 3
  var2  sumvar3 meanvar4
  <chr>   <int>    <dbl>
1 K           7     13.5
2 L           9     14.5
3 M          11     15.5
4 N          13     16.5
5 O          15     17.5

答案 1 :(得分:1)

这是一个解决方案(我希望)。使用您拥有的公式创建数据框列表:

library(tidyverse)

# Create sample data frame
data <- data.frame(var1 = sample(1:2, 5, replace = T),
                   var2 = sample(1:2, 5, replace = T),
                   var3 = sample(1:2, 5, replace = T),
                   varM = sample(1:2, 5, replace = T),
                   var5 = rnorm(5, 3, 6),
                   var6 = rnorm(5, 3, 6))

# Vars to be grouped (var1 until varM in this example)
vars_to_be_used <- names(select(data, var1:varM))

# Function to be used
group_fun <- function(x, .df = data) {
  .df %>%
      group_by_(.x) %>%
      summarise(sumVar5  = sum(var5),
                meanVar6 = mean(var6))
  }

# Loop over vars
results <- map(vars_to_be_used, group_fun)

# Nice list names
names(results) <- vars_to_be_used

print(results)