【问题标题】:How can I reshape my data.table efficiently如何有效地重塑我的 data.table
【发布时间】:2013-05-12 19:28:23
【问题描述】:

我有一个data.table DT

set.seed(1)
DT <- data.table(x=rep(c(1,2,3),each=4), y=c("A","B"), v=sample(1:100,12))
DT
    x y   v
 1: 1 A  29
 2: 1 B  92
 3: 1 A 100
 4: 1 B  82
 5: 2 A  28
 6: 2 B  26
 7: 2 A  18
 8: 2 B  22
 9: 3 A  30
10: 3 B  96
11: 3 A  15
12: 3 B   4

我想像下面这样扩展它,为x 的每个值创建一个新列并报告v 值,数据中不应该有任何结构(而不​​是像下面这样的块)

    x y v.1  v.2 v.3
 1: 1 A  29   NA  NA
 2: 1 B  92   NA  NA
 3: 1 A 100   NA  NA
 4: 1 B  82   NA  NA
 5: 2 A  NA   28  NA
 6: 2 B  NA   26  NA
 7: 2 A  NA   18  NA
 8: 2 B  NA   22  NA
 9: 3 A  NA   NA  30
10: 3 B  NA   NA  96
11: 3 A  NA   NA  15
12: 3 B  NA   NA   4

我问了一个非常相似的问题here,但无法适应 G Grothendieck 当时给我们的答案...

编辑: 像往常一样,我在写完帖子后几乎得到它......我只需要用 NA 替换那些 0(我可能会在 v 中得到 0,我希望能够将 v==0 与丢失的项目分离)

DT2 <- DT[, {SUM.<-factor(x); data.table(model.matrix(~ SUM.:v + 0))}]
txtR) DT2
    SUM.1:v SUM.2:v SUM.3:v
 1:      29       0       0
 2:      92       0       0
 3:     100       0       0
 4:      82       0       0
 5:       0      28       0
 6:       0      26       0
 7:       0      18       0
 8:       0      22       0
 9:       0       0      30
10:       0       0      96
11:       0       0      15
12:       0       0       4

【问题讨论】:

    标签: r data.table reshape


    【解决方案1】:

    可以简单地遍历x 并使用data.table 赋值:

    setkey(DT, x)
    for (i in unique(DT$x)) {
      DT[J(i), paste0("v.", i) := v]
    }
    

    附:我真的希望以下工作,但.GRP 在那里不可用:

    DT[, paste0("v.", .GRP) := v, by = x]
    

    编辑另一个解决方案(试图让上述.GRP 想法以某种方式工作),使用rbind.fill(我没有非常小心地运行长凳,但这似乎可以很好地扩展)

    library(plyr)
    
    cbind(DT,
          rbind.fill(DT[, list(list(setnames(data.table(v), paste0("v.", .GRP)))),
                          by = x]$V1))
    

    【讨论】:

    • +1。回复:第二个想法,这听起来像是一个很好的功能请求,嗯?
    • 如果请求启用DT[, paste0("v.", .GRP) := v, by = x] 的功能,如果它包含一个指定填充值的工具,以防需要NA 以外的其他值。
    • @Frank,我支持这个。但我认为这在以前的某个时候已经提出过.. iirc。而且我认为这将是迄今为止最快的,特别是因为列已经分配在 data.table..
    【解决方案2】:
    set.seed(1)
    DT <- data.table(x=rep(c(1,2,3),each=4), y=c("A","B"), v=sample(1:100,12))
    

    这给了

        x y  v
     1: 1 A 27
     2: 1 B 37
     3: 1 A 57
     4: 1 B 89
     5: 2 A 20
     6: 2 B 86
     7: 2 A 97
     8: 2 B 62
     9: 3 A 58
    10: 3 B  6
    11: 3 A 19
    12: 3 B 16
    

    接下来,答案:

    ux <- unique(DT$x)
    DT[,c(v.=lapply(ux,function(i)v[x==i])),by="x,y"]
    

    给了

        x y v.1 v.2 v.3
     1: 1 A  27  NA  NA
     2: 1 A  57  NA  NA
     3: 1 B  37  NA  NA
     4: 1 B  89  NA  NA
     5: 2 A  NA  20  NA
     6: 2 A  NA  97  NA
     7: 2 B  NA  86  NA
     8: 2 B  NA  62  NA
     9: 3 A  NA  NA  58
    10: 3 A  NA  NA  19
    11: 3 B  NA  NA   6
    12: 3 B  NA  NA  16
    

    该答案可能会在 R 的更高版本中中断,但 OP 指出这也有效并且可能更快:

    DT[,paste0("v.",ux):=lapply(ux,function(i)v[x==i]),by="x"]
    

    【讨论】:

    • 我觉得by=x足够了?
    • 嗯,所需的输出无论如何都有一个“y”列。如果不将其放入 by,我是否必须执行合并或 DT[,c(list(y=y),v.=lapply(1:3,function(i)v[x==i])),by="x"] 之类的操作?
    • @Frank,我想是的。您当前对 by="x,y" 的回答与 OP 的要求不同。仔细查看您为列获得的值并与我的比较..(除了 NA,我仍然不知道如何在创建 model.matrix 时替换它)。
    • @statquant 好的,你是对的。我已将其更改为遍历所有 x 值。
    • DT[,paste0("v.",ux):=lapply(ux,function(i)v[x==i]),by="x"] 效果更好(而且可能更快)
    【解决方案3】:

    这是一种方法:

    tt <- model.matrix(data=DT, ~ factor(x):rep(1, nrow(DT)) + 0)
    tt[tt==0] <- NA
    cbind(DT, DT$v * tt)
    #     x y   v factor(x)1:v factor(x)2:v factor(x)3:v
    #  1: 1 A  69           69           NA           NA
    #  2: 1 B  39           39           NA           NA
    #  3: 1 A  76           76           NA           NA
    #  4: 1 B  49           49           NA           NA
    #  5: 2 A 100           NA          100           NA
    #  6: 2 B  95           NA           95           NA
    #  7: 2 A  36           NA           36           NA
    #  8: 2 B  73           NA           73           NA
    #  9: 3 A  86           NA           NA           86
    # 10: 3 B  20           NA           NA           20
    # 11: 3 A  59           NA           NA           59
    # 12: 3 B  12           NA           NA           12
    

    【讨论】:

    • 你看到用 NA 替换那些 0 的技巧了吗?太糟糕了,因为它很快……
    • @statquant,不是直截了当,但我已经做到了.. 请检查编辑。
    • @statquant,您的意思是在运行时或代码行(或两者)方面高效?
    猜你喜欢
    • 2019-02-05
    • 2016-10-15
    • 2019-02-28
    • 2019-11-17
    • 2013-04-17
    • 2017-11-04
    • 2019-01-10
    • 2018-09-18
    • 2016-08-28
    相关资源
    最近更新 更多