data.table,计算与最后一天值的差异

data.table, calculate difference to last day value

我有一个 data.table:

library(data.table)

dt = structure(list(date = c("01.01.2020", "01.01.2020", "02.01.2020", 
                             "02.01.2020", "03.01.2020", "03.01.2020", "04.01.2020", "04.01.2020"
), name = c("10AFC25D", "FA1A310C", "10AFC25D", "FA1A310C", "10AFC25D", 
            "FA1A310C", "10AFC25D", "FA1A310C"), value = c(100L, 50L, 80L, 
                                                           60L, 70L, 60L, 50L, 80L)), row.names = c(NA, -8L), class = c("data.table", "data.frame"))
dt[, date:=as.Date(date, format="%d.%m.%Y")]

看起来像:

> dt
         date     name value
1: 01.01.2020 10AFC25D   100
2: 01.01.2020 FA1A310C    50
3: 02.01.2020 10AFC25D    80
4: 02.01.2020 FA1A310C    60
5: 03.01.2020 10AFC25D    70
6: 03.01.2020 FA1A310C    60
7: 04.01.2020 10AFC25D    50
8: 04.01.2020 FA1A310C    80

目标: 我想计算两个新列,它们给出了最后一天值的差异。一列显示绝对差异,另一列显示相对差异。公式应该是我可以将延迟从 1 天更改为 7 天(如果我想比较相同的工作日)或任何其他值的灵活性。

预期输出应如下所示:

         date     name value diff_absolut diff_relative
1: 01.01.2020 10AFC25D   100           NA            NA
2: 01.01.2020 FA1A310C    50           NA            NA
3: 02.01.2020 10AFC25D    80          -20    -0.2000000
4: 02.01.2020 FA1A310C    60           10     0.2000000
5: 03.01.2020 10AFC25D    70          -10    -0.1250000
6: 03.01.2020 FA1A310C    60            0     0.0000000
7: 04.01.2020 10AFC25D    50          -20    -0.2857143
8: 04.01.2020 FA1A310C    80           20     0.3333333

我可以这样解决:

dt2 = copy(dt)
dt2[, date:=date+days(1)]

dt_final = merge(dt, dt2, by=c("date", "name"), all.x=TRUE, suffixes=c("", "_2"))
dt_final[, `:=`(diff_absolute=value-value_2, diff_relative=(value-value_2)/value_2, value_2=NULL)]
dt_final

         date     name value diff_absolute diff_relative
1: 2020-01-01 10AFC25D   100            NA            NA
2: 2020-01-01 FA1A310C    50            NA            NA
3: 2020-01-02 10AFC25D    80           -20    -0.2000000
4: 2020-01-02 FA1A310C    60            10     0.2000000
5: 2020-01-03 10AFC25D    70           -10    -0.1250000
6: 2020-01-03 FA1A310C    60             0     0.0000000
7: 2020-01-04 10AFC25D    50           -20    -0.2857143
8: 2020-01-04 FA1A310C    80            20     0.3333333

这可以正常工作,但看起来并不十分优雅和高效。由于原始数据有 1 到 24 行 Mio,我想我最好问问是否有人有更流畅的解决方案?请 data.table 而已。非常感谢。

如果您从行的角度考虑,应该这样做:

lag = 2L
dt[, diff_absolut := shift(value, n = lag) - value]
dt[, diff_relative := diff_absolut / shift(value, n = lag)]

像这样?

为了更长的滞后时间,在 shift-函数

中设置 n 参数
dt[, `:=`(diff_absolute = value - shift(value),
          diff_relative = (value - shift(value)) / shift(value)), 
   by = .(name)][]