考虑以下(示例)zoo
对象:
数据框在日期索引上按升序排序。ma3字段提供持续时间字段的 3 天移动平均值。比较字段将duration值的值与对应的ma3值进行比较;(1) IF持续时间> ma3 THEN 'ABOVE',(2) IF持续时间< ma3 THEN 'BELOW',(3) ELSE 'EQUAL'。
consec_day字段的值计算如下:从具有ma3 值的最早日期开始,如果比较值等于“ABOVE”,则consec_day值的符号为正,如果比较值等于“BELOW”,则符号为consec_day值为负,如果比较值等于“EQUAL”,则consec_day 值为零。要确定consec_day值的大小,请计算连续(从最旧到最近)相同的比较值的数量。
问题:
- consec_day字段的计算可以向量化吗?
- 如果是这样,怎么做?
我当前的解决方案使用如下循环:
z0 <- zoo(matrix(c(c(345, 432, 112, 332, 496, 414, 211), c(NA, NA, 296.33, 292, 313.33, 414, 373.67), c(NA, NA, 'BELOW', 'ABOVE', 'ABOVE', 'EQUAL', 'BELOW'), c(NA, NA, -1, 1, 2, 0, -1)), nrow = 7, ncol = 4), seq(as.Date('2013-07-31'), as.Date('2013-08-06'), by = "day"))
colnames(z0) <- c("duration", "ma3", "comparison", "consec_day")
require(xts)
for (r in 1:nrow(z0)) {
if (is.na(z0$comparison[r])) {next}
if (z0$comparison[r] == 'EQUAL') {z0$consec_day[r] <- 0; next}
if (is.na(z0$comparison[r - 1])) {z0$consec_day[r] <- ifelse(z0$comparison[r] == 'ABOVE', 1, ifelse(z0$comparison[r] == 'BELOW', -1, 0)); next}
if ( (xts::coredata(df0)[r, 3] != xts::coredata(df0)[r - 1, 3]) & xts::coredata(df0)[r, 3] == 'ABOVE') {
df0$consec_day[r] <- 1
} else {
if ( (xts::coredata(df0)[r, 3] != xts::coredata(df0)[r - 1, 3]) & xts::coredata(df0)[r, 3] == 'BELOW') {
df0$consec_day[r] <- -1
} else {ifelse((xts::coredata(df0)[r, 3] != xts::coredata(df0)[r - 1, 3]) & xts::coredata(df0)[r, 3] == 'ABOVE')), df0$consec_day[r] <- df0$consec_day[r - 1] + 1, df0$consec_day[r] <- df0$consec_day[r - 1] - 1}
}