【问题标题】:Transpose duplicated rows to column in R将重复的行转置到 R 中的列
【发布时间】:2013-07-27 11:36:11
【问题描述】:

我有一个大的 data.frame(20000 多个条目),格式如下:

id  D1      D2
1   0.40    0.21
1   0.00    0.00
1   0.53    0.20
2   0.17    0.17
2   0.25    0.25
2   0.55    0.43

每个 id 可以重复 3-20 次。我想将重复的行合并到新列中,所以我的新 data.frame 看起来像:

id  D1      D2      D3      D4      D5      D6
1   0.40    0.21    0.00    0.00    0.53    0.20
2   0.17    0.17    0.25    0.25    0.55    0.43

我之前使用 plyr 操作过 data.frames,但我不确定如何解决这个问题。任何帮助将不胜感激。谢谢。

【问题讨论】:

    标签: r duplicates plyr reshape


    【解决方案1】:

    最好的选择是只使用“reshape2”中的meltdcast。但在我们跳到那个选项之前,让我们看看我们还有什么可用的:


    您提到每个“id”的行数是不平衡的。这会使放入一个整洁的矩形data.frame 有点困难。

    这里有几个例子。

    平衡数据:每个“id”三行

    mydf <- structure(list(id = c(1, 1, 1, 2, 2, 2), 
                           D1 = c(0.4, 0, 0.53, 0.17, 0.25, 0.55), 
                           D2 = c(0.21, 0, 0.2, 0.17, 0.25, 0.43)), 
                      .Names = c("id", "D1", "D2"), row.names = c(NA, 6L), 
                      class = "data.frame")
    mydf
    #   id   D1   D2
    # 1  1 0.40 0.21
    # 2  1 0.00 0.00
    # 3  1 0.53 0.20
    # 4  2 0.17 0.17
    # 5  2 0.25 0.25
    # 6  2 0.55 0.43
    

    有了这些数据,你可以直接使用aggregate

    do.call(data.frame, aggregate(. ~ id, mydf, as.vector))
    #   id D1.1 D1.2 D1.3 D2.1 D2.2 D2.3
    # 1  1 0.40 0.00 0.53 0.21 0.00 0.20
    # 2  2 0.17 0.25 0.55 0.17 0.25 0.43
    

    不平衡数据:一些解决方法

    如果您为“id = 2”添加了第四个值,aggregate 在此处将不起作用:

    mydf[7, ] <- c(2, .44, .33)
    do.call(data.frame, aggregate(. ~ id, mydf, as.vector))
    # Error in data.frame(`0` = c(0.4, 0, 0.53), `1` = c(0.17, 0.25, 0.55, 0.44 : 
    #   arguments imply differing number of rows: 3, 4
    

    最好只使用生成的vectors 中的list

    lapply(split(mydf[-1], mydf[[1]]), function(x) unlist(x, use.names=FALSE))
    # $`1`
    # [1] 0.40 0.00 0.53 0.21 0.00 0.20
    # 
    # $`2`
    # [1] 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
    # 
    

    或者,如果您坚持使用矩形data.frame,请探索rbind 不平衡数据的几个工具之一,例如,来自“plyr”的rbind.fill

    library(plyr)
    rbind.fill(lapply(split(mydf[-1], mydf[[1]]), 
                      function(x) data.frame(t(unlist(x, use.names=FALSE)))))
    #     X1   X2   X3   X4   X5   X6   X7   X8
    # 1 0.40 0.00 0.53 0.21 0.00 0.20   NA   NA
    # 2 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
    

    不平衡数据:更直接的方法

    或者,您可以使用“reshape2”中的meltdcast,如下所示:

    library(reshape2)
    x <- melt(mydf, id.vars = "id")
    ## ^^ That's not enough information for `dcast`
    ##    We need a "time" variable too, so use `ave`
    ##      to create one according to the number of
    ##      values per ID.
    x$time <- ave(x$id, x$id, FUN = seq_along)
    ## ^^ I would probably actually stop at this point.
    ##    Long data with proper ID and "time" values
    ##      tend to be easier to work with and many
    ##      other functions in R work more nicely with
    ##      this long data format.
    dcast(x, id ~ time, value.var = "value")
    #   id    1    2    3    4    5    6    7    8
    # 1  1 0.40 0.00 0.53 0.21 0.00 0.20   NA   NA
    # 2  2 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      • 2020-02-16
      相关资源
      最近更新 更多