重塑或表格数据从长到宽

时间:2018-05-01 15:19:14

标签: r dataframe subset tapply

我正在使用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循环以及什么不是,但我似乎无法弄明白。如果有人可以帮助我,我会很高兴,我不禁想到我错过了一些非常容易和明显的东西。

如何生成目标输出?

/解决,见下文。感谢您找到一个合适的标题,你们是最好的!

2 个答案:

答案 0 :(得分:1)

您可以使用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

如果您不想要额外的“成绩”列,则可以执行以下操作:

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

答案 1 :(得分:0)

或者,考虑基本R方法,使用:by进行分组,aggregate进行计数,setNames进行组##列名称,Reduce进行链合并dataframes:

# 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

要删除成绩,请在合并后使用transform或直接在final_df上使用

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)