我正在运行两个嵌套的for循环来检查向量的每一行,如果下面的10行中的任何一行是3点,大于3行,则在下面。如果为真,则在新创建的二进制向量上记录1。 (我知道这听起来很复杂,但这种比较允许以交易目的测试时间序列中的条件)
例如,对于第一行,想要检查是否:
第3行>第6 + 3行或
...
第11行>第14 + 3行
(顺便说一句,我需要循环,想法是在数千行上运行,而不仅仅是20行)
以下代码效果很好,但是当其中一个循环超出向量时,它具有产生NA值的不必要特性。
df <- data.frame( LastPrice = c( 1221, 1220, 1230, 1217, 1216, 1218 , 1216, 1216, 1217, 1220, 1219, 1218, 1220, 1216, 1217, 1218, 1218, 1207, 1206, 1205))
df$StrongMoveBinary[j] <- 0
for(j in 1:20) {
tmp <- 0
for (i in 1:10) {
tmp <- tmp + ifelse (df$LastPrice[j+i] - df$LastPrice[j+i+3] > 3, 1, 0)}
df$StrongMoveBinary[j] <- tmp>0}
//Note: purpose of tmp variable is to record every occasion that LastPrice > LastPrice 3 rows below, rather than just the last instance
该代码创建 StrongMoveBinary = 1 1 0 0 1 1 1 NA NA NA NA NA NA NA NA NA NA NA NA 。这是13个NAs。但是有足够的数据只有4个NA。其他9个NA是由于我的编码很差。为了解决这个问题,我修改了代码,以限制&#34; i&#34;给出&#34; j&#34;的值,因此停止&#34; i&#34;循环到矢量外循环。
df$StrongMoveBinary[j] <- 0
for(j in 1:20) {
x <- 0
if (j <= 10) {x=10}
if (j > 10) {x=20-j}
tmp <- 0
for (i in 1:x) {
tmp <- tmp + ifelse (df$LastPrice[j+i] - df$LastPrice[j+i+3] > 3, 1, 0)}
df$StrongMoveBinary[j] <- tmp>0}
不幸的是它不起作用。 StrongMoveBinary仍然有13个NA。任何想法将不胜感激!谢谢。
答案 0 :(得分:1)
我认为最大的问题混淆是由于缺少命名变量。你有几个参数(看 3行,如果 10行中的任何一行,数据框中的行数,要检查的差异多少)但是你只是使用全身数字,很难保持直线。你不应该写20
,你应该写nrow(df)
- 这样,相同的代码可以处理你的20行示例和数千行真实数据。如果任何参数发生变化,您只能在一个地方进行更改。
window = 10 # up to this far below the current row
rows_below = 3 # check against this far down
min_diff = 3 # for a difference at least this big
现在我们将使用这些来显式计算循环的边界。 pmin
是一个非常方便的函数,用于确保我们不会超出数据的范围。 (当然,这些定义应该非常仔细地检查以确保准确性 - 这就是我在撰写关于第17个条目是否应该是NA
的那些挑剔的评论时我正在做的事情。)
base_rows = 1:(nrow(df) - rows_below - 1) # can't check more than this
# for a given base row, this is the maximum row to start checking against
candidate_max = pmin(base_rows + window, nrow(df) - rows_below)
# pre-allocate a vector of results
StrongMoveBinary = integer(length = length(base_rows))
完成所有设置后,我们就可以测试了:
for (i in seq_along(base_rows)) {
StrongMoveBinary[i] = as.numeric(
any(
df$LastPrice[(i + 1):candidate_max[i]] -
df$LastPrice[((i + 1):candidate_max[i]) + rows_below] > min_diff
)
)
}
让我们看看我们得到了什么:
StrongMoveBinary
# [1] 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
我完全离开了NA
。如果您更愿意拥有它们,请预先分配StrongMoveBinary = rep(NA, nrow(df))
,而不是我在顶部进行预分配。
最后,也许我们想把它变成一个可以应用于任何矢量的函数。设置参数非常简单。唯一的编辑是使其适用于向量(使用length()
)而不是数据框的特定行(使用nrow()
)。
strong_indicate = function(x, window = 10, rows_below = 3, min_diff = 3) {
base_rows = 1:(length(x) - rows_below - 1) # can't check more than this
# for a given base row, this is the maximum row to start checking against
candidate_max = pmin(base_rows + window, length(x) - rows_below)
# pre-allocate a vector of results
StrongMoveBinary = integer(length = length(base_rows))
for (i in seq_along(base_rows)) {
StrongMoveBinary[i] = as.numeric(
any(
x[(i + 1):candidate_max[i]] -
x[((i + 1):candidate_max[i]) + rows_below] > min_diff
)
)
}
return(StrongMoveBinary)
}
我们可以在数据栏上调用它:
strong_indicate(x = df$LastPrice)
# [1] 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
我们可以探索其他值会做什么:
strong_indicate(x = df$LastPrice, min_diff = 12)
# [1] 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
strong_indicate(x = df$LastPrice, window = 5)
# [1] 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1