我有一个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行上与“ Created”级别相同的行位置。这意味着第二个峰超过第一个峰。相反,在存储第二个峰数据的第2行中,“下一个峰”值15表示直到第四个峰(即对应于“已创建”列中的“ 15”值)才出现第二个峰。超出了峰值价格水平。
最后,“ Valid_reversal”列表示“ Created”和“ Next_peak”级别是否在预定义的阈值内。例如,第一行中的“ T”表明第5行和第9行(“ Next_peak”)中的峰满足此条件。如果然后转到对应于9的值“ Created”,则还有一个“ T”,这表明15的“ Next_peak”值也符合标准。但是,当我转到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))
不确定我是否正确理解您的要求,可以nafill
在步骤1之后使用:
#step 0 & 1
Test[, out :=
Test[(Valid_reversal)][.SD, on=.(Next_peak=Created), mult="last",
fifelse(is.na(x.Created), i.Created, NA_integer_)]
]
#your steps 2, 3, ...
Test[Valid_reversal | is.na(out), out := nafill(out, "locf")]
编辑新示例。您可以igraph
用来查找链:
#step 0 & 1
Test[, out :=
Test[(Valid_reversal)][.SD, on=.(Next_peak=Created), mult="last",
fifelse(is.na(x.Created), i.Created, NA_integer_)]
]
#steps 2, 3, ...
library(igraph)
g <- graph_from_data_frame(Test[Valid_reversal | is.na(out)])
DT <- setDT(stack(clusters(g)$membership), key="ind")[,
ind := as.numeric(levels(ind))[ind]][,
root := min(ind), values]
Test[Valid_reversal | is.na(out), out := DT[.SD, on=.(ind=Created), root]]
仅出于完整性考虑,以下是while
循环版本:
#step 0 & 1
Test[, out :=
Test[(Valid_reversal)][.SD, on=.(Next_peak=Created), mult="last",
fifelse(is.na(x.Created), i.Created, NA_integer_)]
]
#step 2, 3, ...
while(Test[, any(is.na(out))]) {
Test[is.na(out), out := Test[.SD, on=.(Next_peak=Created), mult="first", x.out]]
}
Test
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句