使用 data.table 选择正确的连接
Selecting correct join with data.table
来自 的跟进。
我有三个数据表(实际的 input
一个更大,性能很重要,所以我必须尽可能多地使用 data.table):
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
) 中的 GDP
和 CPI
值插入到第一个 (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]
将每个 ID 的时间 data.table 连接到其余列,从而扩展 data.table.
宽版的 mevs (dcast(mevs, DATE ~ INDEX_NAME))
然后加入扩展的 data.table.
最后,扩展 data.table 中的缺失值由 zoo
包中的 na.locf
函数填充。
预期输出为:
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
之间的连接选择一定是错误的,但我找不到解决方法。
感谢大家的宝贵时间。
可能的解决方案:
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
来自
我有三个数据表(实际的 input
一个更大,性能很重要,所以我必须尽可能多地使用 data.table):
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
) 中的GDP
和CPI
值插入到第一个 (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]
将每个 ID 的时间 data.table 连接到其余列,从而扩展 data.table.宽版的 mevs
(dcast(mevs, DATE ~ INDEX_NAME))
然后加入扩展的 data.table.最后,扩展 data.table 中的缺失值由
zoo
包中的na.locf
函数填充。
预期输出为:
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
之间的连接选择一定是错误的,但我找不到解决方法。
感谢大家的宝贵时间。
可能的解决方案:
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