重塑或 table 数据从长到宽

reshape or table data from long to wide

我正在使用 R,但我现在真的很茫然。我有这样的数据:

df <- data.frame(
       group = c(2, 2, 2, 1, 1, 0, 0, 1, 1, 0, 1, 0),
       grade = c(2, 4, 3, 1, 3, 2, 5, 1, 1, 2, 3, 1)
)

我想要这样:

  group0  group1  group2
1      1       3       0
2      2       0       1
3      0       2       1
4      0       0       1
5      1       0       0
6      0       0       0

我已经尝试了几个小时使用子集、tapply、table、for 循环等等,但我似乎无法弄清楚。如果有人能帮助我,我会很高兴,我忍不住想我错过了一些非常简单和明显的东西。

我怎样才能产生我的目标输出?

/ 已解决,见下文。顺便说一句,感谢您找到合适的标题,你们是最棒的!

你可以用 dplyrtidyr 做这样的事情:

df %>%
  count(group, grade) %>%
  mutate(group = paste0('group', group)) %>%
  spread(group, n, fill = 0)

# A tibble: 5 x 4
  grade group0 group1 group2
* <int>  <dbl>  <dbl>  <dbl>
1     1      1      3      0
2     2      2      0      1
3     3      0      2      1
4     4      0      0      1
5     5      1      0      0

如果您不想要额外的 'grade' 列,您可以这样做:

df %>%
  count(group, grade) %>%
  mutate(group = paste0('group', group)) %>%
  spread(group, n, fill = 0) %>%
  select(-grade)

  group0 group1 group2
*  <dbl>  <dbl>  <dbl>
1      1      3      0
2      2      0      1
3      0      2      1
4      0      0      1
5      1      0      0

或者,考虑使用基本 R 方法:by 用于分组,aggregate 用于计数,setNames 用于组## 列名,Reduce 用于链合并数据帧:

# DATAFRAME LIST BY EACH GROUP
grp_list <- by(df, df$group, function(d) setNames(aggregate(.~grade, d, FUN=length), 
                                                 c("grade", paste0("group",max(d$group)))))

# CHAIN MERGE (OUTER JOIN)
final_df <- Reduce(function(x,y) merge(x,y, by="grade", all=TRUE), grp_list) 

# FILL NA WITH ZEROS
final_df[is.na(final_df)] <- 0

final_df
#   grade group0 group1 group2
# 1     1      1      3      0
# 2     2      2      0      1
# 3     3      0      2      1
# 4     4      0      0      1
# 5     5      1      0      0

要删除等级,请在链合并后或直接在 final_df:

上使用 transform
final_df <- transform(Reduce(function(x,y) merge(x,y, by="grade", all=TRUE), grp_list), 
                      grade = NULL)

final_df <- transform(final_df, grade = NULL)