【发布时间】:2020-06-25 13:13:26
【问题描述】:
我有一个 data.table,其中包含 3 个输入列,如下所示,第四列代表我的目标输出:
require(data.table)
Test <- data.table(Created = c(5,9,13,15,19,23,27,31,39,42,49),
Next_peak = c(9,15,15,23,27,27,31,39,49,49,50),
Valid_reversal = c(T,T,F,F,T,F,T,F,T,F,F),
Target_output = c(5,5,13,5,19,23,19,19,39,42,39))
我不确定这是否完全有必要,但我会尝试解释数据集,希望能更容易地了解我正在尝试做什么。这在书面上有点难以解释,所以请多多包涵!
“已创建”列表示我正在分析的财务数据时间序列中价格“峰值”(即反转点)的行号位置。 “Next_peak”列表示超过该行峰值的下一个峰值的相应行号(在原始数据集中)。例如查看第 1 行,“Next_peak”值为 9,对应于与此汇总表第 2 行上的“已创建”级别相同的行位置。这意味着第二个峰值超过了第一个峰值。相反,在存储第二个峰值数据的第 2 行中,“下一个峰值”值 15 表明直到第 4 个峰值(即对应于“已创建”列中的“15”值),第二个峰值才出现超过了峰值的价格水平。
最后,“Valid_reversal”列表示“Created”和“Next_peak”水平是否在预定义的阈值内。例如,第一行中的“T”表明第 5 行和第 9 行的峰(“Next_peak”)符合此标准。如果我再去“Created”的值对应的值为9,还有一个“T”,提示“Next_peak”的值为15也符合条件。但是,当我转到第4行Created = 15时,有一个“F”,我们发现下一个峰值不符合标准。
我要做的是链接有效反转点的“链”,然后返回原始起始“创建”值。即我希望第 1、2 和 4 行的值为“5”,这表明这些行的峰值都在原始数据集第 5 行中原始峰值的预定义阈值内。 相反,第 3 行应该简单地返回 13,因为相对于第 13 行形成的峰值,在“Next_peak”值为 15 处没有有效的反转。
我可以使用以下代码创建所需的输出,但是,这不是一个可行的解决方案,因为在我的实际数据集中有超过 3 个与相同“链接”的峰的步骤数很容易超过 3反转点。 我可以用'for'循环来做到这一点,但我想知道是否有更好的方法来做到这一点,最好是尽可能矢量化,因为我使用的实际数据集包含数百万行.
这是我目前的方法:
Test[Valid_reversal == T,Step0 := Next_peak]
Test[,Step1 := sapply(seq_len(.N),function(x) ifelse(any(!(Created[x] %in% Step0[seq_len(x)])),
Created[x],NA))]
Test[,Step2 := unlist(ifelse(is.na(Step1),
lapply(.I,function(x) Step1[which.max(Step0[seq_len(x-1)] == Created[x])]),
Step1))]
Test[,Step3 := unlist(ifelse(is.na(Step2),
lapply(.I,function(x) Step2[which.max(Step0[seq_len(x-1)] == Created[x])]),
Step2))]
如您所见,虽然该数据集只需要 3 次迭代,但我所采用的方法中的步骤数无法提前定义(据我所知)。因此,要实现这种方法,我必须重复第 2 步,直到计算完所有值,可能通过“while”循环。我正在努力弄清楚如何做到这一点。
如果您对如何以更有效的方式解决此问题有任何想法,请告诉我。
提前致谢,
菲尔
编辑:请注意,我在上面没有提到“Next_peak”值不一定单调增加。上面的示例意味着可以使用 nafill,但是,正如以下示例/示例输出所示,它不会在以下实例中给出正确的输出:
Test <- data.table(Created = c(5,9,13,15,19,23,27,31,39,42,49),
Next_peak = c(27,15,15,19,23,27,42,39,42,49,50),
Valid_reversal = c(T,T,F,T,F,F,T,F,F,T,F),
Target_output = c(5,9,13,9,9,23,5,31,39,5,5))
【问题讨论】:
标签: r data.table