Использование списка для хранения результатов двойного цикла (цикла for) в R

Я хочу произвести расчеты для элементов отдельных строк с помощью цикла for. У меня есть два data.frames

  1. df: содержит данные по акциям всех торговых дней
  2. события: содержит данные только о днях событий акций

Несмотря на то, что для этого конкретного примера может быть гораздо более простой подход, я хотел бы знать, как выполнить такую ​​задачу с помощью цикла в цикле (for-loops).

Во-первых, мои data.frames:

comp1 <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3)
date1 <- c(1,2,3,4,5,1,2,3,4,5,1,2,3,4,5)
ret <- c(1.2,2.2,-0.5,0.98,0.73,-1.3,-0.02,0.3,1.1,2.0,1.9,-0.98,1.45,1.71,0.03)
df <- data.frame(comp1,date1,ret)
comp2 <- c(1,1,2,2,2,3,3)
date2 <- c(2,4,1,2,5,4,5)
q <- paste("")
events <- data.frame(comp2,date2,q)

df

#    comp1 date1   ret
# 1      1     1  1.20
# 2      1     2  2.20
# 3      1     3 -0.50
# 4      1     4  0.98
# 5      1     5  0.73
# 6      2     1 -1.30
# 7      2     2 -0.02
# 8      2     3  0.30
# 9      2     4  1.10
# 10     2     5  2.00
# 11     3     1  1.90
# 12     3     2 -0.98
# 13     3     3  1.45
# 14     3     4  1.71
# 15     3     5  0.03

events

#   comp2 date2 q
# 1     1     2  
# 2     1     4  
# 3     2     1  
# 4     2     2  
# 5     2     5  
# 6     3     4  
# 7     3     5  

Я хочу произвести расчеты df $ ret. В качестве примера возьмем 2 * df $ ret. Результаты для каждого события-дня должны храниться в mylist. Конечным результатом должны быть «события» data.frame со столбцом «q», в котором я хочу сохранить результаты вычислений.

# important objects:
companies <- as.vector(unique(df$comp1)) # all the companies (here: 1, 2, 3)
days <- as.vector(unique(df$date1)) # all the trading-days (here: 1, 2, 3, 4, 5)
mylist <- vector('list', length(companies)) # a list where the results should be stored for each company

Я придумал код, который не работает. Но я все же думаю, что это должно выглядеть примерно так:

for(i in 1:nrow(events)) {
  events_k <- events[which(comp1==companies[i]),] # data of all event days of company i
  df_k <- df[which(comp2==companies[i]),] # data of all trading days of company i

  for(j in 1:nrow(df_k)) {
    events_k[j, "q"] <- df_k[which(days==events_k[j,"date2"]), "ret"] * 2


  }
  mylist[i] <- events_k   
}

Я не понимаю, как настроить цикл внутри другого цикла и как сохранить результаты в моем списке. Любая помощь приветствуется !!

Спасибо!


person cptn    schedule 03.04.2014    source источник


Ответы (1)


Не расстраивайся. Все ваши проблемы - обычные ошибки R. Сначала попробуйте изменить

events <- data.frame(comp2,date2,q,stringsAsFactors=FALSE)

раньше вместо этого. Ваш столбец q неявно преобразуется в коэффициент, что запрещает арифметические * 2 операции позже.

Далее рассмотрим фиксированный цикл

for(i in 1:nrow(events)) {
  events_k <- events[which(comp1==companies[i]),] # data of all event days of company i
  df_k <- df[which(comp2==companies[i]),] # data of all trading days of company i

  for(j in 1:nrow(df_k)) {
    events_k[j, "q"] <-
      if (0 == length(tmp <- df_k[which(days==events_k[j,"date2"]), "ret"] * 2)) NA
      else tmp
  }
  mylist[[i]] <- events_k
}

Ваша первая проблема была в последней строке, где вы использовали [ вместо [[ (в R первое означает всегда заключенный в список, тогда как последний фактически обращался к значению в списке).

Вторая проблема заключается в том, что иногда which(days==events_k[j,"date2"]) равно numeric(0) (т.е. нет подходящей даты события). После этого код будет работать, но у вас по-прежнему будет много фреймов данных с NAs. Чтобы удалить их, вы можете сделать что-то вроде:

mylist <- Filter(function(df) nrow(df) > 0,
  lapply(mylist, function(df) df[apply(df, 1, function(row) !all(is.na(row))), ]))

который отфильтрует элементы списка с пустыми фреймами данных и строки в фреймах данных со всеми NA.

person Robert Krzyzanowski    schedule 03.04.2014
comment
Спасибо за Ваш ответ! для первого входа первой компании ваш подход работает, но не для других мероприятий! это почему? - person cptn; 05.04.2014