Ссылки на условия в нескольких строках (цикл for)

У меня возникают проблемы со ссылками на условия, которые имеют место в нескольких строках, с использованием цикла for.

Идея заключается в следующем. Есть датафрейм с колонками LastPrice и KCT. Хотите добавить столбец SignalBinary в фрейм данных, и если

1) LastPrice[j] > KCT[j] в любых 3 последовательных строках, &

2) LastPrice[j+1] - LastPrice [j+1+3] > 12 в любой из строк от j+1 до j+1+10 (т.е. на 10 строк ниже)

затем хотите записать 1 в SignalBinary[i].

df <- data.frame(nrow =20, ncol =2)
df <- data.frame(LastPrice = c(1221,1220,1220,1217,1216,1218,1216,1216,1217,1220,1219,1218,1220,1216,1217,1218,1218,1207,1206,1205), KCT = c(1218,1218,1219,1218,1221,1217,1217,1216,1219,1216,1217,1216,1219,1217,1218,1217,1217,1217,1219,1217))
df$SignalBinary <-for(j in1:20){for(i in1:10){ifelse (df$LastPrice[j]> df$KCT[j]& df$LastPrice[j+1]> df$KCT[j+1]& df$LastPrice[j+2]> df$KCT[j+2]& df$LastPrice[j+i]- df$LastPrice[j+i+3]>12,1,0)}}

Основываясь на данных, можно было бы ожидать, что код будет записывать 1 в строках 10 и 11 и 0 в остальных. Но я делаю что-то не так. Запуск кода не выдает сообщения об ошибке, но и не создает df$SignalBinary. Запуск df$SignalBinary говорит NULL.

Кстати, цель этого состоит в том, чтобы применить код к большой базе данных цен, чтобы запустить статистику по бинарным сигналам.

Надеюсь, кто-то может помочь. Большое спасибо


person Krug    schedule 07.04.2016    source источник
comment
Вот одна проблема, подумайте о том, когда i=20 и j=10 при доступе к df$LastPrice[j+i]. Вы пытаетесь получить доступ к строке 30 из набора данных, состоящего всего из 20 строк. ifelse() не выдает ошибку в этом   -  person Steve_Corrin    schedule 07.04.2016
comment
Ты прав. Но не знаю, как это исправить, к сожалению.   -  person Krug    schedule 08.04.2016


Ответы (2)


Одна вещь, которая неверна, заключается в том, что вы ничего не возвращаете из своего оператора ifelse (в настоящее время у вас есть 1 и 0 в качестве действий, если условие (не) выполнено). Я думаю (но не цитируйте меня), что я решил вашу проблему более простым способом, без использования вложенного цикла for.

df <- data.frame(nrow = 20, ncol = 2)
df <- data.frame(LastPrice = c( 1221, 1220, 1220, 1217, 1216,  1218 , 1216, 1216, 1217, 1220,     1219, 1218, 1220, 1216, 1217, 1218, 1218, 1207, 1206, 1205), KCT = c( 1218, 1218, 1219, 1218, 1221,  1217 , 1217, 1216, 1219, 1216, 1217, 1216, 1219, 1217, 1218, 1217, 1217, 1217, 1219, 1217))

df$SignalBinary <- as.numeric(df$LastPrice >= df$KCT & 
                      c(rep(FALSE ,3), diff(df$LastPrice, lag=3) >= 3)) 

Поэтому я установил два условия, которые должны быть выполнены для вектора. Во-первых, df$LastPrice должно быть больше (или равно) df$KCT. Во-вторых, запаздывающая разница между df$LastPrice должна быть больше или равна 3. Я дополняю первые 3 значения FALSE, чтобы сделать два вектора сопоставимой длины. Если оба условия соблюдены, он записывает TRUE, который я конвертирую в числовой, а затем помещаю новый столбец в data.frame.

Просто замените значения, которые вы указали в своем игрушечном примере, значениями, которые вам нужны для вашего приложения, и я думаю, что это должно сработать.

person Tad Dallas    schedule 07.04.2016
comment
Большое спасибо за помощь!! Подобное использование diff делает разницу между одной строкой и тремя предыдущими строками. Мне нужна разница между одной строкой и каждой из трех предыдущих строк. Можно было бы повторить функцию diff 3 раза, но только упрощенная задача, представленная здесь, сравнивается с 3. На самом деле нужно сравнить по крайней мере с 20, а в некоторых случаях намного больше, поэтому не думайте, что есть способ обойти цикл for. Кроме того, вы пропустили третье (более сложное) условие (то есть искать разницу только в 10 предыдущих строках, а не в каждой строке). В любом случае спасибо, дал пищу для размышлений. - person Krug; 08.04.2016

Решено! Публикация решения. Оказался значительно сложнее, чем я думал. Пришлось изменить размер StrongMove с 12 на 3, иначе не было бы сигналов, учитывая данные, которые я предоставил в этом примере.

#Data
df <- data.frame(LastPrice = c( 1221, 1220, 1220, 1217, 1216,  1218 , 1216, 1216, 1217, 1220, 1219, 1218, 1220, 1216, 1217, 1218, 1218, 1207, 1206, 1205), KCT = c( 1218, 1218, 1219, 1218, 1221,  1217 , 1217, 1216, 1219, 1216, 1217, 1216, 1219, 1217, 1218, 1217, 1217, 1217, 1219, 1217))

#Define inputs
StrongMoveWindow = 10     # up to this far below the current row
StrongMoveDur = 3         # check row against another this far down
StrongMoveSize = 3        # for a difference at least this big
PvsKCTDur = 3

#Set variables and define loop boundaries
base_rows = 1:(nrow(df) - StrongMoveDur)  # can't check more than this
candidate_max = pmin(base_rows + StrongMoveWindow, nrow(df) - StrongMoveDur) # for a given base row, this is the maximum row to start checking against
df$StrongMove = rep(NA, nrow(df))
df$SignalBinary = rep(NA, nrow(df)) # pre-allocate a vector of results

#Make StrongMove variable
for (i in seq_along(base_rows)) {
  df$StrongMove[i] = as.numeric(
    any(
      df$LastPrice[(i + 1):candidate_max[i]] - 
        df$LastPrice[((i + 1):candidate_max[i]) + StrongMoveDur] > StrongMoveSize))}

#Make ContPvsKCT variable
library(data.table)
setDT(df)
df[, SingPvsKCT := as.integer(LastPrice > KCT)]
df[, ContPvsKCT := do.call(pmin, shift(SingPvsKCT, 0:(PvsKCTDur-1), type="lead"))]

#Make SignalBinary variable
df$SignalBinary <- ifelse (df$ContPvsKCT == 1 & df$StrongMove == 1, 1, 0)

Большое спасибо @Грегору @HubertL @Chris @Psidom @brittenb @Frank

person Krug    schedule 15.04.2016