计算分组数据框中多列中因子的出现次数

Ols*_*ard 4 r reshape dataframe

我有以下数据框,想要按grp列分组以查看每个组中出现的每个列值的数量。

> data.frame(grp = unlist(strsplit("aabbccca", "")), col1=unlist(strsplit("ABAABBAB", "")), col2=unlist(strsplit("BBCCCCDD", "")))
  grp col1 col2
1   a    A    B
2   a    B    B
3   b    A    C
4   b    A    C
5   c    B    C
6   c    B    C
7   c    A    D
8   a    B    D
Run Code Online (Sandbox Code Playgroud)

期望的结果:

  grp col1A col1B col2B col2C col2D
1   a    1    2     2     0     1
2   b    2    0     0     2     0
3   c    1    2     0     2     1
Run Code Online (Sandbox Code Playgroud)

如果我只查看grpcol1列,很容易使用 来解决这个问题table(),并且当只有 2 列时,我可以与table(df[c('grp', 'col1')])合并table(df[c('grp', 'col2')])。然而,随着因子列数量的增加,这会变得极其麻烦,并且如果col1和之间存在共享值,则会出现问题col2

请注意,dplyr 的计数不起作用,因为它会查找 col1 和 col2 的唯一组合。

我尝试使用 tidyr 熔化和传播数据框,但没有任何运气

> pivot_longer(df, c(col1, col2), names_to= "key", values_to = "val") %>% pivot_wider("grp", names_from = c("key", "val"), values_from = 1, values_fn = sum)
Error in `stop_subscript()`:
! Can't subset columns that don't exist.
x Column `grp` doesn't exist.
Run Code Online (Sandbox Code Playgroud)

我可以找到很多适用于有 1 个组列和 1 个值列的情况的解决方案,但我不知道如何将它们推广到更多列。

Dar*_*sai 5

您可以将col1&堆叠col2在一起,计算每个组合的数量,然后将表格转换为宽形式。

library(dplyr)
library(tidyr)

df %>%
  pivot_longer(col1:col2) %>%
  count(grp, name, value) %>%
  pivot_wider(grp, names_from = c(name, value), names_sort = TRUE,
              values_from = n, values_fill = 0)

# A tibble: 3 x 6
  grp   col1_A col1_B col2_B col2_C col2_D
  <chr>  <int>  <int>  <int>  <int>  <int>
1 a          1      2      2      0      1
2 b          2      0      0      2      0
3 c          1      2      0      2      1
Run Code Online (Sandbox Code Playgroud)

解决base方案(感谢@GKi完善代码):

table(cbind(df["grp"], col=do.call(paste0, stack(df[-1])[2:1])))

   col
grp col1A col1B col2B col2C col2D
  a     1     2     2     0     1
  b     2     0     0     2     0
  c     1     2     0     2     1
Run Code Online (Sandbox Code Playgroud)

  • 这里有两件事值得注意并且非常有帮助。1. 使用 `id_cols` 和 2. `names_sort` 参数。 (2认同)