使用列表在 R 中存储双循环(for 循环)的结果



我想使用 for 循环对单个行的元素进行计算。我有两个数据帧

  1. DF:包含所有交易日股票的数据
  2. 事件:仅包含股票事件天数的数据

尽管这个特定示例可能有一种更简单的方法,但我想知道如何使用循环中的循环(for-loops)执行此类任务。

首先,我的数据帧:

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 中。最终输出应该是带有"q"列的 data.frame "events",我希望在其中存储计算结果。

# 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   
}

我不明白如何在另一个循环中设置循环以及如何将结果存储在 mylist 中。任何帮助感谢!!

谢谢!

不要难过。你所有的问题都是常见的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)(即,没有匹配的事件日期)。然后,代码将起作用,但您仍然会有很多带有 NA 的数据帧。要删除它们,您可以执行以下操作:

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

这将过滤掉具有空数据框的列表元素,以及数据框中具有所有NA的行。

最新更新