【问题标题】:reshape or table data from long to wide [duplicate]从长到宽重塑或表格数据[重复]
【发布时间】:2018-05-01 15:19:13
【问题描述】:

我正在使用 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、表格、for 循环等几个小时,但我似乎无法弄清楚。如果有人可以帮助我,我会非常高兴,我不禁认为我错过了一些非常简单和明显的东西。

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

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

【问题讨论】:

  • 为什么结果有六行?
  • @Dason 我认为因为有 6 个可能的等级
  • 每个年级一个 (1:6)。
  • 我怀疑 op 想要 with(data, table(factor(grade, levels=1:6), group)) 但如果他们能确认详细信息就好了
  • @Leo 这些是您需要包含的详细信息。我们为什么要怀疑您的数据中没有实际存在的成绩?

标签: r dataframe subset tapply


【解决方案1】:

你可以用dplyr和tidyr做这样的事情:

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

【讨论】:

  • 这非常有效。谢谢!
【解决方案2】:

或者,考虑使用基本 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

要删除等级,请在链合并后使用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)

【讨论】:

    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2015-08-04
    相关资源
    最近更新 更多