【问题标题】:R spreading multiple columns with tidyr [duplicate]R用tidyr传播多列[重复]
【发布时间】:2015-08-16 00:14:47
【问题描述】:

取这个样本变量

df <- data.frame(month=rep(1:3,2),
                 student=rep(c("Amy", "Bob"), each=3),
                 A=c(9, 7, 6, 8, 6, 9),
                 B=c(6, 7, 8, 5, 6, 7))

我可以使用tidyr 中的spread 将其更改为宽格式。

> df[, -4] %>% spread(student, A)
  month Amy Bob
1     1   9   8
2     2   7   6
3     3   6   9

但是我怎样才能传播两个值,例如AB,输出类似于

  month Amy.A Bob.A Amy.B Bob.B
1     1     9     8     6     5
2     2     7     6     7     6
3     3     6     9     8     7

【问题讨论】:

    标签: r dataframe dplyr tidyr


    【解决方案1】:

    这是一个使用data.table 的既简单又非常有效的解决方案

    library(data.table) ## v >= 1.9.6
    dcast(setDT(df), month ~ student, value.var = c("A", "B")) 
    #    month Amy_A Bob_A Amy_B Bob_B
    # 1:     1     9     8     6     5
    # 2:     2     7     6     7     6
    # 3:     3     6     9     8     7
    

    或者可能的tidyr 解决方案

    df %>% 
      gather(variable, value, -(month:student)) %>%
      unite(temp, student, variable) %>%
      spread(temp, value)
    
    #   month Amy_A Amy_B Bob_A Bob_B
    # 1     1     9     6     8     5
    # 2     2     7     7     6     6
    # 3     3     6     8     9     7
    

    2019 年 10 月 22 日编辑

    正如 @gjabel 在 cmets 中所述,较新的 tidyr 版本 (v1.0.0+) 现在有pivot_widerpivot_longer 函数(当前处于maturing 状态),因此,一种更新的方法将是

    pivot_wider(data = df, 
                id_cols = month, 
                names_from = student, 
                values_from = c("A", "B"))
    # # A tibble: 3 x 5
    #     month A_Amy A_Bob B_Amy B_Bob
    #     <int> <dbl> <dbl> <dbl> <dbl>
    #   1     1     9     8     6     5
    #   2     2     7     6     7     6
    #   3     3     6     9     8     7
    

    【讨论】:

    • @PolarBear 你想如何处理骗子?你想求和?意思是?尝试data.table 解决方案并将fun.aggregate = sum 添加到dcast
    • @PolarBear spreadgather 并非旨在应用函数。您可能需要为此使用dplyr。或者你可以使用dcast,就像我上面建议的那样。或者,如果您对此感到强烈,可以发布一个新问题。
    • 我为这些做了一个基准测试:*.com/a/54889598/2563804
    • pivot_wider(data = df, id_cols = month, names_from = student, values_from = c("A", "B")) 应该在 tidyr 1.0.0 或更高版本中工作
    • pivot_wider 也适用于不带引号的变量名称(在本例中为 A 和 B),即 pivot_wider(data = df, id_cols = month, names_from = student, values_from = c(A, B))