【问题标题】:R How to join by condition with data.table?R如何按条件加入data.table?
【发布时间】:2021-06-06 20:30:21
【问题描述】:

经过一些研究,特别是在这里,我发现了一种我认为非常有趣的方法,可以通过条件加入两个data.tableDT[WHERE, v := FROM[.SD, on=, x.v]] .

很遗憾,尽管尝试了很多次,我还是无法执行此操作。

从 DT1 和 DT2,我需要创建 DTres :只对一些 DT1 行执行连接。

而DT3是我失败的尝试之一……

可以这样做吗?怎么做?

非常感谢您的帮助。

library(data.table)

DT1 <- data.table(crit = rep(c('AA', 'BB', 'CC', 'DD'),each = 3),
                  num = rep(1:3, 4), 
                  val = rnorm(12)^2)
DT1

DT2 <- data.table(BB = c(1,3),
                  cross = c(128, 183))
DT2

DTres <- data.table(crit = rep(c('AA', 'BB', 'CC', 'DD'),each = 3),
                    num = rep(1:3, 4), 
                    val = rnorm(12)^2,
                    cross = c(rep(NA,3), 128, NA, 183, rep(NA, 6))
)
DTres

DT3 <- DT1[crit == 'BB', cross := DT2[DT1, on = .('BB' = num), x.cross]]

【问题讨论】:

    标签: r join data.table


    【解决方案1】:

    在第二个数据集中创建一列'crit',进行连接并将'cross'的值从'DT2'分配给'DT1'

    DT1[DT2[,  c(.(crit = 'BB'), .SD)] , cross := cross, on = .(crit, num = BB)]
    
    DT1
    

    或者melt第二个数据变成'long'格式

    DT1[ melt(DT2, id.var = 'cross', variable.name = 'crit'), 
          cross := cross, on = .(crit, num = value)]
    
    
    
    DT1
    #    crit num          val cross
    # 1:   AA   1 4.720241e+00    NA
    # 2:   AA   2 2.261093e-01    NA
    # 3:   AA   3 5.040239e-01    NA
    # 4:   BB   1 3.729867e-01   128
    # 5:   BB   2 8.725384e-01    NA
    # 6:   BB   3 1.571597e+00   183
    # 7:   CC   1 8.494091e-02    NA
    # 8:   CC   2 1.965077e-01    NA
    # 9:   CC   3 1.221802e-06    NA
    #10:   DD   1 5.526632e-03    NA
    #11:   DD   2 3.475349e-01    NA
    #12:   DD   3 3.233841e-01    NA
    

    或者基于 OP 的尝试的另一个选项是

    DT1[crit == 'BB' & num %in% DT2$BB, 
          cross := .SD[DT2, on = .(num = BB)]$cross]
    

    【讨论】:

    • 谢谢,您的第一个选项对我很有用!另外,我可以加入 DT3 来“更新”我的交叉变量吗? DT3 &lt;- data.table(DD = c(2,3), cross = c(99, 787)) ?
    • 编辑:从您在堆栈上的一篇较早的帖子中,我测试了DT1[DT3[, c(.(crit = 'DD'), .SD)] , cross := ifelse(is.na(cross), i.cross, cross), on = .(crit, num = DD)]。它似乎运行良好。你确认了吗?谢谢!!
    • 你可以在data.table中使用fifelse
    • 是的,这只是一个疏忽。感谢监督。
    【解决方案2】:

    这是另一个data.table 选项

    DT2[, c(stack(.SD[, .(BB)]), .(cross = cross))][DT1, on = .(ind = crit, values = num)]
    

    给了

        values ind cross          val
     1:      1  AA    NA 0.0080997625
     2:      2  AA    NA 0.0001964834
     3:      3  AA    NA 1.2621554895
     4:      1  BB   128 1.8066857886
     5:      2  BB    NA 2.3200035029
     6:      3  BB   183 0.1780571706
     7:      1  CC    NA 1.8521153969
     8:      2  CC    NA 3.0757963595
     9:      3  CC    NA 2.4597679400
    10:      1  DD    NA 1.6815750082
    11:      2  DD    NA 0.0564519787
    12:      3  DD    NA 1.4985435547
    

    【讨论】:

      猜你喜欢
      • 2013-08-09
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      • 2015-05-12
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多