当循环超出向量时过滤 NA 值(定义循环边界)
Filtering NA values when loop goes outside vector (defining loop boundaries)
我正在 运行 设置两个嵌套的 for 循环来检查向量的每一行,如果下面的 10 行中的任何一行比下面的 3 行大 3 个点。如果为真,则在新创建的二进制向量上记录 1。 (我知道这听起来很复杂,但是这种比较允许测试时间序列中的条件以用于交易目的)
例如,对于第一行,要检查是否:
- 第 2 行 > 第 5 行 + 3 或
第 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 NA NA。那是 13 个 NA。但是有足够的数据只有 4 个 NA。其他 9 个 NA 是我编码不当的结果。为了解决这个问题,我修改了代码,以在给定 "j" 的值的情况下限制 "i" 的值,从而停止 "i" 循环以在向量外循环。
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。任何想法将不胜感激!谢谢。
我认为混淆的最大问题是缺少命名变量。你有几个参数(看下面 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
我正在 运行 设置两个嵌套的 for 循环来检查向量的每一行,如果下面的 10 行中的任何一行比下面的 3 行大 3 个点。如果为真,则在新创建的二进制向量上记录 1。 (我知道这听起来很复杂,但是这种比较允许测试时间序列中的条件以用于交易目的)
例如,对于第一行,要检查是否:
- 第 2 行 > 第 5 行 + 3 或
第 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 NA NA。那是 13 个 NA。但是有足够的数据只有 4 个 NA。其他 9 个 NA 是我编码不当的结果。为了解决这个问题,我修改了代码,以在给定 "j" 的值的情况下限制 "i" 的值,从而停止 "i" 循环以在向量外循环。
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。任何想法将不胜感激!谢谢。
我认为混淆的最大问题是缺少命名变量。你有几个参数(看下面 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