【问题标题】:R data.table calculations with previous row dependenciesR data.table 计算与先前的行依赖关系
【发布时间】:2019-02-02 12:37:56
【问题描述】:

以下是我目前在 Excel 中计算的一些数据。

col_A   col _B  col_C col_D col_E   col_F    col_G
-1.5%   0.010   1.00    1   1.00     -       -   
-5.4%   0.024   1.00    1   1.00     0.01   -0.00 
-7.9%   0.036   1.00    1   1.00     0.02   -0.00 
-12.7%  0.052   0.99    1   0.99     0.06   -0.01 
-4.6%   0.049   0.98    1   0.98     0.19   -0.01 
-8.3%   0.051   0.95    1   0.95     0.39   -0.03 
-7.3%   0.052   0.88    1   0.88     1.00   -0.07 
-9.2%   0.055   0.69    1   0.69     2.31   -0.21 
-7.9%   0.055   0.38    1   0.38     5.63   -0.44 
-2.2%   0.051   0.29    1   0.29     11.13  -0.24 

我一直在尝试使用 data.table 在 R 中执行计算。我遇到的问题是 data.table 按列执行计算。由于依赖于前一行值的结果,我需要逐行执行计算。下面给出了计算列的 Excel 公式,“T”表示“当前行”,“T-1”表示“上一行”

col_C: (col_C.T-1) * (1 + col_G.T)

col_D:最大值(Col_C.T,col_D.T-1)

col_E: (col_C.T / col_D.T)

col_F: 最大值 ((1 - (col_C.T-1 / col_D.T-1)) / col B.T-1), 0.01)

col_G: col_A * col_F

非常感谢任何帮助。

【问题讨论】:

  • 我假设您正在寻找 data.table::shift 来滞后/领先条目?
  • 我发现使用 data.table::shift 取得了一些成功。但是,每一列的计算都依赖于上一行的结果,没有正确捕获。
  • (1) shift 允许您根据以前的 row 条目计算值,所以我想shift 是这里的方法; (2) 但是,我确实很难理解您的“规则”,这在我看来是循环的。例如,C 列中的条目基于 G 列,而 G 列又依赖于 F 列,而 F 列又依赖于 C 列。
  • 是的,令人头疼的是依赖关系。请注意,它会从 T 跳转到 T-1,例如当 F 回到 C 时。
  • 是的,我明白,但你的问题陈述不是很清楚(对我来说);我们仍然需要某些列的初始值。例如,C、D 和 E 列的第一行值是否总是1.0

标签: r data.table


【解决方案1】:

好的,所以这不是一个答案,但评论太长了。

请仔细检查您的规则!它们与输入和预期输出不一致。

为了演示,我们以第 2 行和第 3 行为例

col_A   col _B  col_C col_D col_E   col_F    col_G
...
-5.4%   0.024   1.00    1   1.00     0.01   -0.00 
-7.9%   0.036   1.00    1   1.00     0.02   -0.00 

并根据您的规则计算i = 3 行的col_F 值:

col_F[i] = max((1 - col_C[i - 1] / col_D[i - 1]) / col_B[i - 1], 0.01)
         = max((1 - 1 / 1) / 0.024, 0.01)
         = max(0, 0.01)
         = 0.01

因此,col_F 在第 3 行中的值应该是 0.01 而不是 0.02

有可能:

  1. 您的规则不正确,或者
  2. col_Ccol_Dcol_E 中第 1 行条目的起始值不正确。

无论哪种方式,目前输入数据、预期输出和规则不一致。

【讨论】:

  • 对我来说,规则很好。您观察到的差异是由于发布的值的精度有限。我在 Excel 中输入公式进行仔细检查。 col_C 的第 3 行中的值计算为 0.99946,以 2 位精度打印为 1.00
  • @Uwe “您观察到的差异是由于发布的值的精度有限” 嗯,真的吗?我所做的只是使用了 OP 提供的数字。他没有在任何地方提到数字是四舍五入的,他似乎也没有在任何地方提供对原始数据的访问。我不使用 Excel,所以我不确定您检查的方式/内容。我没有看到我上面的例子失败的地方。
【解决方案2】:

如果没有其他条件需要使用data.table,我建议使用矩阵实现逐行计算:

m <- data.matrix(dt)
m[, 3:7] <- NA

for (i in seq.int(nrow(m))) {
  if (i == 1L) {
    m[i, "col_F"] <- 0
    m[i, "col_G"] <- 0 
    m[i, "col_C"] <- 1
    m[i, "col_D"] <- 1
  } else {
    m[i, "col_F"] <- max((1 - (m[i-1, "col_C"] / m[i-1, "col_D"])) / m[i-1, "col_B"], 0.01)
    m[i, "col_G"] <- m[i, "col_A"] * m[i, "col_F"]
    m[i, "col_C"] <- m[i-1, "col_C"] * (1 + m[i, "col_G"])
    m[i, "col_D"] <- max(m[i, "col_C"], m[i-1, "col_D"])
  }
m[i, "col_E"] <- m[i, "col_C"] / m[i, "col_D"]  
}

m
       col_A col_B     col_C col_D     col_E       col_F        col_G
 [1,] -0.015 0.010 1.0000000     1 1.0000000  0.00000000  0.000000000
 [2,] -0.054 0.024 0.9994600     1 0.9994600  0.01000000 -0.000540000
 [3,] -0.079 0.036 0.9976835     1 0.9976835  0.02250000 -0.001777500
 [4,] -0.127 0.052 0.9895302     1 0.9895302  0.06434834 -0.008172239
 [5,] -0.046 0.049 0.9803653     1 0.9803653  0.20134322 -0.009261788
 [6,] -0.083 0.051 0.9477596     1 0.9477596  0.40070748 -0.033258721
 [7,] -0.073 0.052 0.8768905     1 0.8768905  1.02432085 -0.074775422
 [8,] -0.092 0.055 0.6858958     1 0.6858958  2.36749020 -0.217809099
 [9,] -0.079 0.055 0.3764416     1 0.3764416  5.71098585 -0.451167882
[10,] -0.022 0.051 0.2825483     1 0.2825483 11.33742486 -0.249423347

col_F 的最后 4 行与 OP 的预期结果的偏差可能是由于 col_Acol_B 的发布值的精度有限。

数据

library(data.table)

dt <- fread("col_A   col_B  col_C col_D col_E   col_F    col_G
-1.5%   0.010   1.00    1   1.00     -       -   
-5.4%   0.024   1.00    1   1.00     0.01   -0.00 
-7.9%   0.036   1.00    1   1.00     0.02   -0.00 
-12.7%  0.052   0.99    1   0.99     0.06   -0.01 
-4.6%   0.049   0.98    1   0.98     0.19   -0.01 
-8.3%   0.051   0.95    1   0.95     0.39   -0.03 
-7.3%   0.052   0.88    1   0.88     1.00   -0.07 
-9.2%   0.055   0.69    1   0.69     2.31   -0.21 
-7.9%   0.055   0.38    1   0.38     5.63   -0.44 
-2.2%   0.051   0.29    1   0.29     11.13  -0.24 ", na.strings = "-")
# convert percent string to numeric
dt[, col_A := readr::parse_number(col_A) / 100]

【讨论】:

    猜你喜欢
    • 2018-09-30
    • 2021-11-26
    • 2015-11-09
    • 2020-12-25
    • 2014-09-11
    • 2013-06-06
    • 2013-03-02
    • 2013-01-19
    相关资源
    最近更新 更多