2016-04-07 7 views
0

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

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

1) LastPrice [J]> БФК [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, и 0s в состоянии покоя. Но я делаю что-то неправильно. Запуск кода не дает сообщения об ошибке, но он не создает df $ SignalBinary. Запуск df $ SignalBinary говорит NULL.

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

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

+0

Вот одна проблема, думаю о том, когда я = 20 и J = 10 при доступе к ф.р. $ LastPrice [J + I ]. Ваша попытка получить доступ к строке 30 из набора данных всего за 20 строк. ifelse() не выдает ошибку на этом –

+0

Вы правы. Но не знаю, как это исправить, к сожалению. – Krug

ответ

0

Решенный! Проводка решения. Было значительно сложнее, чем я думал. При изменении размера 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) 

Большое спасибо @Gregor @HubertL @Psidom @brittenb @ Крис @Frank

0

Неверная вещь заключается в том, что вы ничего не возвращаете из своего оператора 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.

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

+0

Большое спасибо за помощь! Используя «diff», как это делает разницу между одной строкой и тремя строками ранее. Мне нужна разница между одной строкой и каждой из трех предыдущих строк. Мог бы повторить функцию diff 3 раза, но только упрощенная проблема, представленная здесь, сравнивается с 3. На самом деле вы хотите сравнить, по крайней мере, 20, в некоторых случаях гораздо больше, поэтому не думайте, что есть путь вокруг цикла for. Кроме того, вы упустили третье (более сложное) условие (т.е. искать разницу только в 10 строках ранее, а не в каждой строке).Спасибо в любом случае, дал мне немного еды для размышлений. – Krug