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)
如果我只查看grp和col1列,很容易使用 来解决这个问题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 个值列的情况的解决方案,但我不知道如何将它们推广到更多列。
您可以将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)