【问题标题】:Selecting correct join with data.table使用 data.table 选择正确的连接
【发布时间】:2018-12-12 17:32:37
【问题描述】:

this question 的后续跟进。

我有三个数据表(实际的input 一个更大,性能很重要,所以我必须尽可能多地使用):

input <- fread("  ID   | T1 | T2 | T3 |    DATE    
                ACC001 |  1 |  0 |  0 | 31/12/2016 
                ACC001 |  1 |  0 |  1 | 30/06/2017 
                ACC002 |  0 |  1 |  1 | 31/12/2016", sep = "|")

mevs <- fread("  DATE    | INDEX_NAME | INDEX_VALUE 
              31/12/2016 | GDP        |  1.05       
              30/06/2017 | GDP        |  1.06       
              31/12/2017 | GDP        |  1.07       
              30/06/2018 | GDP        |  1.08       
              31/12/2016 | CPI        |  0.02       
              30/06/2017 | CPI        |  0.00       
              31/12/2017 | CPI        | -0.01       
              30/06/2018 | CPI        |  0.01   ", sep = "|")

time <- fread("    DATE   
               31/12/2017 
               30/06/2018 ", sep = "|")

有了这些,我需要实现两件事:

  • 将第二个 dt(mevs) 中的 GDPCPI 值插入到第一个 (input) 中,以根据 T1、@987654330 在最后一列中进行一些计算@、T3GDPCPI

  • 对第三个 dt (time) 中给定的时间间隔进行投影,将前一个间隔中的 T1T2T3 值复制到相同的 ID 中(所以 ACC001如果存在则保留1, 0, 1)(如果不存在则用0 填充)并从相应的日期获取GDPCPI

为此,我使用以下代码:

ones <- input[, .N, by = ID][N == 1, ID]

input[, .SD[time, on = "DATE"], by = ID
      ][dcast(mevs, DATE ~ INDEX_NAME), on = "DATE", `:=` (GDP = i.GDP, CPI = i.CPI)
        ][, (2:4) := lapply(.SD, function(x) if (.BY %in% ones) replace(x, is.na(x), 0L) else zoo::na.locf(x) )
          , by = ID, .SDcols = 2:4][]

哪个(感谢@Jaap):

  • input[, .SD[time, on = "DATE"], by = ID] 将每个 ID 的时间 data.table 连接到其余列,从而扩展 data.table。

  • 然后将一个宽版本的 mevs (dcast(mevs, DATE ~ INDEX_NAME)) 加入到扩展的 data.table 中。

  • 最后用zoo包中的na.locf函数填充了扩展data.table中的缺失值。

预期的输出是:

       ID T1 T2 T3       DATE  GDP   CPI
1: ACC001  1  0  0 31/12/2016 1.05  0.02
2: ACC001  1  0  1 30/06/2017 1.06  0.00
3: ACC001  1  0  1 31/12/2017 1.07 -0.01
4: ACC001  1  0  1 30/06/2018 1.08  0.01
5: ACC002  0  1  1 31/12/2016 1.05  0.02
6: ACC002  0  0  0 30/06/2017 1.06  0.00
7: ACC002  0  0  0 31/12/2017 1.07 -0.01
8: ACC002  0  0  0 30/06/2018 1.08  0.01

但我得到的是:

       ID T1 T2 T3       DATE  GDP   CPI
1: ACC001 NA NA NA 31/12/2017 1.07 -0.01
2: ACC001 NA NA NA 30/06/2018 1.08  0.01
3: ACC002 NA NA NA 31/12/2017 1.07 -0.01
4: ACC002 NA NA NA 30/06/2018 1.08  0.01

我几乎可以肯定,在第一步中,inputtime 之间的连接选择肯定是错误的,但我找不到解决方法。

感谢大家的宝贵时间。

【问题讨论】:

    标签: data.table r join data.table na


    【解决方案1】:

    一个可能的解决方案:

    times <- unique(rbindlist(list(time, as.data.table(unique(input$DATE))))
                    )[, DATE := as.Date(DATE, "%d/%m/%Y")][order(DATE)]
    input[, DATE := as.Date(DATE, "%d/%m/%Y")]
    mevs[, DATE := as.Date(DATE, "%d/%m/%Y")]
    
    ones <- input[, .N, by = ID][N == 1, ID]
    
    input[, .SD[times, on = "DATE"], by = ID
          ][dcast(mevs, DATE ~ INDEX_NAME), on = "DATE", `:=` (GDP = i.GDP, CPI = i.CPI)
            ][, (2:4) := lapply(.SD, function(x) if (.BY %in% ones) replace(x, is.na(x), 0L) else zoo::na.locf(x) )
              , by = ID, .SDcols = 2:4][]
    

    给出:

           ID T1 T2 T3       DATE  GDP   CPI
    1: ACC001  1  0  0 2016-12-31 1.05  0.02
    2: ACC001  1  0  1 2017-06-30 1.06  0.00
    3: ACC001  1  0  1 2017-12-31 1.07 -0.01
    4: ACC001  1  0  1 2018-06-30 1.08  0.01
    5: ACC002  0  1  1 2016-12-31 1.05  0.02
    6: ACC002  0  0  0 2017-06-30 1.06  0.00
    7: ACC002  0  0  0 2017-12-31 1.07 -0.01
    8: ACC002  0  0  0 2018-06-30 1.08  0.01
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-28
      • 2014-05-01
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      相关资源
      最近更新 更多