Выбор правильного соединения с data.table - PullRequest
0 голосов
/ 04 июля 2018

Продолжение от этого вопроса .

У меня есть три таблицы данных (фактическая 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 = "|")

С этим мне нужно достичь 2 вещей:

  • Вставьте значения GDP и CPI из второго dt (mevs) в первый (input), чтобы выполнить некоторые вычисления в последнем столбце на основе T1, T2, T3, GDP и CPI.

  • Сделайте прогноз для интервалов времени, указанных в третьем dt (time), скопировав значения T1, T2 и T3 в предыдущем интервале в том же ID (так, ACC001 они останутся 1, 0, 1), если он существует (заполняя их 0, если его нет) и получая GDP и CPI от соответствующих дат.

Для этого я использую следующие фрагменты кода:

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] объединяет для каждого идентификатора таблицу данных времени с оставшимися столбцами, расширяя таблицу данных.

  • Затем расширенная версия mevs (dcast(mevs, DATE ~ INDEX_NAME)) присоединяется к расширенной таблице data.table.

  • Наконец, пропущенные значения в расширенной таблице data.table заполняются функцией na.locf из пакета zoo.

Предполагаемый результат будет:

       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

Я почти уверен, что на первом этапе это должен быть неправильный выбор соединения между input и time, но я не могу найти обходной путь для этого.

Спасибо всем за ваше время.

1 Ответ

0 голосов
/ 04 июля 2018

Возможное решение:

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
...