【问题标题】:dcast in r with duplicates and no aggregation在 r 中进行 dcast,具有重复项且没有聚合
【发布时间】:2017-02-25 02:25:26
【问题描述】:

我在这里查看了许多类似的问题,但找不到解决这种情况的答案。我的数据框是这样的:

SET SP   T1  T2  T3
A   dog  1  0   0
A   cat  0  NA  4
A   bird 5  0   NA
B   cat  2  0   0
B   bird NA 3   0
C   dog  1  0   0
C   cat  0  0   6
C   bird 0  0   0
D   dog  NA 22  1

其中 SET 被故意重复多次,每条记录都包含一个 SP 和多个 TRIALS (T1-3) 的值。

我想要的是一个宽数据框,如下所示。没有任何类型的求和/平均/数学运算:

SET DOG_T1  DOG_T2  DOG_T3  CAT_T1  CAT_T2  CAT_T3  BIRD_T1 BIRD_T2 BIRD_T3
142   1     0       0      0        NA      4       5       0       NA
255  NA     NA     NA      2        0       0       NA      3       0
336   1     0      0       0        0       6       0       0       0
66   NA    22      1       NA       NA      NA      NA      NA      NA

我尝试了以下方法,但收到错误,melt 和 dcast 默认为长度。这会将 SET 变量变成不同的数字,并且只为值填充 0 和 1。

df %>% 
  group_by(SET, SP) %>% 
  melt(id.vars = c('SET','SP')) %>%
  data.table::dcast(SP + variable ~ SET, fun.aggregate = NULL, value.var = 'value')

这在我没有任何重复的 SET 时有效,但在我包含完整数据集后立即失败。 注意:我的真实数据框大约有 250 万行,所以速度很重要。

【问题讨论】:

    标签: r data-cleaning


    【解决方案1】:

    这是dcast.data.table 擅长的情况。它允许多个参数作为“value.var”,允许非常简洁的语法:

    library(data.table)
    dcast(df, SET ~ SP, value.var=c("T1", "T2", "T3"))
    #   SET T1_bird T1_cat T1_dog T2_bird T2_cat T2_dog T3_bird T3_cat T3_dog
    #1:   A       5      0      1       0     NA      0      NA      4      0
    #2:   B      NA      2     NA       3      0     NA       0      0     NA
    #3:   C       0      0      1       0      0      0       0      6      0
    #4:   D      NA     NA     NA      NA     NA     22      NA     NA      1
    

    【讨论】:

    • 感谢您的回复。但是,这仍然会导致“默认长度”错误。我在上面放置的 melt() 步骤之前和之后都尝试过。我同意 dcast 应该能够在这里工作(根据我的阅读),但似乎无法实现。
    • 这不是错误,而是警告。数据中有重复项。当有 Set A 和 T1 和bird 的两个条目时,你想做什么?
    • 正如您在上面看到的,该条目只有一个插槽,这就是摘要的作用。您想将这些值相加吗?平均?等等……
    【解决方案2】:

    按照上面的@lukeA,但在dcast() 函数调用中添加fun.aggregate = identityfun.aggregate = list 参数

    【讨论】:

      【解决方案3】:

      你可以试试

      library(tidyverse)
      df <- read.table(header=T, text="
      SET SP   T1  T2  T3
      A   dog  1  0   0
      A   cat  0  NA  4
      A   bird 5  0   NA
      B   cat  2  0   0
      B   bird NA 3   0
      C   dog  1  0   0
      C   cat  0  0   6
      C   bird 0  0   0
      D   dog  NA 22  1")
      df %>% 
        gather(var, val, -(1:2)) %>% 
        unite("SP", SP, var) %>% 
        spread(SP, val)
      #   SET bird_T1 bird_T2 bird_T3 cat_T1 cat_T2 cat_T3 dog_T1 dog_T2 dog_T3
      # 1   A       5       0      NA      0     NA      4      1      0      0
      # 2   B      NA       3       0      2      0      0     NA     NA     NA
      # 3   C       0       0       0      0      0      6      1      0      0
      # 4   D      NA      NA      NA     NA     NA     NA     NA     22      1
      

      【讨论】:

      • 感谢您的回复。在您的示例中,“var”和“val”是我上面描述的融化语句的变量和值结果,还是其他?
      • var为变量,包含t1到t3,val为对应列的值。
      • 更新:我能够让它运行,但它引发了关于我在 SET 中的重复标识符的错误。通过将最后一行从 spread() 更改为 reshape 解决了这个问题:df %&gt;% gather(var, val, -(7:8)) %&gt;% unite("SP", SP, var) %&gt;% reshape(idvar = 'SET', timevar = 'SP', direction = 'wide')
      【解决方案4】:

      由于我目前的声誉不允许在上面的@lukeA 答案中添加评论,因此我将其作为一个新答案,这更像是一个建议:

      使用data.table 函数setcolorder 可以将列重新排序为“bird_T1、cat_T1、dog_T1、bird_T2、cat_T2 等”。通过使用类似于

      的自定义函数
      newOrder <- function() {
      
            lapply(1:max(index)
                   , function(i) grep(
                                       sprintf('%s', i)
                                                 , names(DT), value = TRUE)
              )}
      
      

      其中index 是为允许dcast.data.table 用于重复键(例如上面初始表中的SET 变量)而创建的索引:

      DT[, index := 1:.N, by = SET]
      
      

      最终以常规方式实现新订单:

      setcolorder(dcast(DT), neworder = newOrder())
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2020-06-21
        相关资源
        最近更新 更多