Dplyr 将组汇总为列名

Dplyr Summarise Groups as Column Names

我得到了一个包含很多列的数据框,想用多个函数对它们进行汇总。

test_df <- data.frame(Group = sample(c("A", "B", "C"), 10, T), var1 = sample(1:5, 10, T), var2 = sample(3:7, 10, T))

test_df %>% 
  group_by(Group) %>% 
  summarise_all(c(Mean = mean, Sum = sum))

    # A tibble: 3 x 5
  Group var1_Mean var2_Mean var1_Sum var2_Sum
  <chr>     <dbl>     <dbl>    <int>    <int>
1 A          3.14      5.14       22       36
2 B          4.5       4.5         9        9
3 C          4         6           4        6

这会导致第一行组名和列名与前一列名和函数名的组合。 期望的结果是 table,前面的列名作为第一行,组和函数在列名中。

我可以用

实现
test_longer <- test_df %>% pivot_longer(cols = starts_with("var"), names_to = "var", values_to = "val")

# Add row number because spread needs unique identifiers for rows
test_longer <- test_longer %>% 
  group_by(Group) %>% 
  mutate(grouped_id = row_number())

spread(test_longer, Group, val) %>% 
  select(-grouped_id) %>% 
  group_by(var) %>% 
  summarise_all(c(Mean = mean, Sum = sum), na.rm = T)

    # A tibble: 2 x 7
  var   A_Mean B_Mean C_Mean A_Sum B_Sum C_Sum
  <chr>  <dbl>  <dbl>  <dbl> <int> <int> <int>
1 var1    3.14    4.5      4    22     9     4
2 var2    5.14    4.5      6    36     9     6

但这好像绕了比较长的弯路。。。应该有更好的方法,但是没找到。有什么建议么?谢谢

有很多方法可以解决这个问题,但我会通过首先转向更长的数据框来简化它,然后按 vargroup 分组。然后你可以转动得更宽以获得你想要的最终结果。请注意,我使用 summarize(across()) 替换了已弃用的 summarize_all(),即使只有一个列可以手动指定 Mean = ...Sum = ....

set.seed(123)

test_df %>%
  pivot_longer(
    var1:var2,
    names_to = "var"
  ) %>%
  group_by(Group, var) %>%
  summarize(
    across(
      everything(),
      list(Mean = mean, Sum = sum),
      .names = "{.fn}"
    ),
    .groups = "drop"
  ) %>%
  pivot_wider(
    names_from = "Group",
    values_from = c(Mean, Sum),
    names_glue = "{Group}_{.value}"
  )
#> # A tibble: 2 × 7
#>   var   A_Mean B_Mean C_Mean A_Sum B_Sum C_Sum
#>   <chr>  <dbl>  <dbl>  <dbl> <int> <int> <int>
#> 1 var1       1    2.5    3.2     1    10    16
#> 2 var2       5    4.5    4.4     5    18    22