我不确定我是否正确,因此,我将首先展示我要解决的问题,然后再展示我要解决的问题。随时告诉我我有多严重,以及您能想到的任何更好的方法。
我有3个data.tables(实际的“输入”数据要大得多,并且性能很重要,因此我必须尽可能多地使用data.table):
输入:
+--------+----+----+----+------------+
| 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 |
| ACC002 | 0 | 1 | 1 | 30/06/2017 |
+--------+----+----+----+------------+
重要程度:
+------------+------------+-------------+
| 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 |
+------------+------------+-------------+
时间:
+------------+
| DATE |
+------------+
| 31/12/2016 |
| 30/06/2017 |
| 31/12/2017 |
| 30/06/2018 |
+------------+
有了这些,我需要实现两件事:
将第二个dt(mevs)中的GDP和CPI值插入第一个dt(mevs)中,以便根据T1,T2,T3,GDP和CPI在最后一列中进行一些计算。
对第三个dt(时间)中给出的时间间隔进行投影,将前一个间隔中的T1,T2和T3值复制到相同的ID中(这样ACC001的值将保持(1、0、1) ),然后从相应日期获取GDP和CPI。最终的计算将使用相同的函数完成。
应该导致这样的“输入” dt:
+--------+----+----+----+------------+------+-------+------+
| ID | T1 | T2 | T3 | DATE | GDP | CPI | CALC |
+--------+----+----+----+------------+------+-------+------+
| ACC001 | 1 | 0 | 0 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC001 | 1 | 0 | 1 | 30/06/2017 | 1.06 | 0.00 | fun |
| ACC001 | 1 | 0 | 1 | 31/12/2017 | 1.07 | -0.01 | fun |
| ACC001 | 1 | 0 | 1 | 30/06/2018 | 1.08 | 0.01 | fun |
| ACC002 | 0 | 1 | 1 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC002 | 0 | 1 | 1 | 30/06/2017 | 1.06 | 0.00 | fun |
| ACC002 | 0 | 1 | 1 | 31/12/2017 | 1.07 | -0.01 | fun |
| ACC002 | 0 | 1 | 1 | 30/06/2018 | 1.08 | 0.01 | fun |
+--------+----+----+----+------------+------+-------+------+
我设法做到的事情:
mevs <- mevs %>% tidyr::spread(INDEX_NAME, INDEX_VALUE)
将索引值放入列中。input[mevs, ':=' (GDP = i.GDP, CPI = i.CPI), on = "RUN_DATE"]
设置索引值(如果我没记错的话,请避免赋值)。结果:
+--------+----+----+----+------------+------+------+------+
| ID | C1 | C2 | C3 | DATE | GDP | CPI | CALC |
+--------+----+----+----+------------+------+------+------+
| ACC001 | 1 | 0 | 0 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC001 | 1 | 0 | 1 | 30/06/2017 | 1.06 | 0 | fun |
| ACC002 | 0 | 1 | 1 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC002 | 0 | 1 | 1 | 30/06/2017 | 1.06 | 0 | fun |
+--------+----+----+----+------------+------+------+------+
我不知道该怎么做:
我正在尝试使用基于“ DATE”的“ input”-“ time”和以下代码进行正确的外部联接(在“我在做什么”的第二步的“选择性联接”之前) :input <- input[time, on = "DATE"]
。但是,这不仅不能正常工作(我在下一步需要的ID列中获得了NA),而且还迫使我进行分配。
在那之后,我计划基于“ ID”使用“ input”-“ input”进行另一个联接,但是显然我不能,因为在这些新行中没有任何ID值:
+--------+----+----+----+------------+
| ID | T1 | T2 | T3 | DATE |
+--------+----+----+----+------------+
| ACC001 | 1 | 0 | 0 | 31/12/2016 |
| ACC001 | 1 | 0 | 1 | 30/06/2017 |
| NA | NA | NA | NA | 31/12/2017 |
| NA | NA | NA | NA | 30/06/2018 |
| ACC002 | 0 | 1 | 1 | 31/12/2016 |
| ACC002 | 0 | 1 | 1 | 30/06/2017 |
| NA | NA | NA | NA | 31/12/2017 |
| NA | NA | NA | NA | 30/06/2018 |
+--------+----+----+----+------------+
例如,是否有任何方法可以根据DATE列上的某些条件复制这些ID?如果不是,您是否知道其他解决方案,也许基于rbindlist
?
非常感谢您所做的一切。任何建议将不胜感激!
避免分配
@Jaap的解决方案因此返回了所需的data.table。除非不可避免,否则我需要将输入转换为最后一个data.table,而不使用标准分配(<-
)。在这种情况下该怎么办?
条件
我需要在票据的最后一部分中引入特殊性。如果在投影之前有一个没有任何注册表的ID,则T1 / T2 / T3在投影中必须为0。此处就是ACC002,在2016年12月31日之前没有注册表:
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 = "|")
那应该最终变成:
+--------+----+----+----+------------+------+-------+------+
| ID | T1 | T2 | T3 | DATE | GDP | CPI | CALC |
+--------+----+----+----+------------+------+-------+------+
| ACC001 | 1 | 0 | 0 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC001 | 1 | 0 | 1 | 30/06/2017 | 1.06 | 0.00 | fun |
| ACC001 | 1 | 0 | 1 | 31/12/2017 | 1.07 | -0.01 | fun |
| ACC001 | 1 | 0 | 1 | 30/06/2018 | 1.08 | 0.01 | fun |
| ACC002 | 0 | 1 | 1 | 31/12/2016 | 1.05 | 0.02 | fun |
| ACC002 | 0 | 0 | 0 | 30/06/2017 | 1.06 | 0.00 | fun |
| ACC002 | 0 | 0 | 0 | 31/12/2017 | 1.07 | -0.01 | fun |
| ACC002 | 0 | 0 | 0 | 30/06/2018 | 1.08 | 0.01 | fun |
+--------+----+----+----+------------+------+-------+------+
实际的最终结论是,在这种情况下,依赖于T1 / T2 / T3多项式的CALC列等于0(以防万一,您可以直接从那里求近)。
答案 0 :(得分:1)
使用:
input[, .SD[time, on = "DATE"], by = ID
][dcast(mevs, DATE ~ INDEX_NAME), on = "DATE", `:=` (GDP = i.GDP, CPI = i.CPI)
][, (2:4) := lapply(.SD, zoo::na.locf), by = ID, .SDcols = 2:4][]
给予:
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 1 1 30/06/2017 1.06 0.00 7: ACC002 0 1 1 31/12/2017 1.07 -0.01 8: ACC002 0 1 1 30/06/2018 1.08 0.01
这是什么:
input[, .SD[time, on = "DATE"], by = ID]
将ID
data.table的每个time
连接到其余列,从而扩展了data.table。mevs
(dcast(mevs, DATE ~ INDEX_NAME)
)加入扩展的data.table。na.locf
函数填充。要满足已更新问题的额外条件,您可以执行以下操作:
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][]
给出:
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
使用的数据:
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
ACC002 | 0 | 1 | 1 | 30/06/2017 ", 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/2016
30/06/2017
31/12/2017
30/06/2018 ", sep = "|")