如何将来自for循环的数据存储在for循环内? (r中的滚动相关)

Posted

技术标签:

【中文标题】如何将来自for循环的数据存储在for循环内? (r中的滚动相关)【英文标题】:How to store data from for loop inside of for loop? (rolling correlation in r) 【发布时间】:2016-11-25 04:07:19 【问题描述】:
require(quantmod)
require(TTR)

iris2 <- iris[1:4]
b=NULL
for (i in 1:ncol(iris2))
for (j in 1:ncol(iris2))
a<- runCor(iris2[,i],iris2[,j],n=21)
b<-cbind(b,a)

我想计算数据框中不同列的滚动相关性,并按列分别存储数据。尽管上面的代码将数据存储到变量 b 中,但它并不像只是转储所有结果那样有用。我想要的是能够为每个 i 创建不同的数据框。

在这种情况下,由于我有 4 列,我最终想要的是 4 个数据帧,每个数据帧包含 4 列显示滚动相关性,即 df1 = col 1 与 col 1、2、3、4 的 corr,df2 = corr col 2 vs col 1,2,3,4...等)

我曾想过使用 lapply 或 rollapply,但遇到了同样的问题。

d=NULL
for (i in 1:ncol(iris2))
 for (j in 1:ncol(iris2))
c<-rollapply(iris2, 21 ,function(x) cor(x[,i],x[,j]), by.column=FALSE)
d<-cbind(d,c)  

非常感谢任何意见。

【问题讨论】:

在索引向量上尝试foreach 循环或mapply。它会给你一个 DF 列表的列表。嵌套由 i 然后 j 然后 c&amp;d 在 for 循环中使用 cbind 绝不是一个好主意。使用具有预定义长度的列表以避免在内存中过度复制是更好的做法。 【参考方案1】:

如果你想保持扩展循环,数据帧列表怎么样?

e <- list(length = length(ncol(iris2)))

for (i in 1:ncol(iris2)) 
  d <- matrix(0, nrow = length(iris2[,1]), ncol = length(iris2[1,]))
    for (j in 1:ncol(iris2)) 
        d[,j]<- runCor(iris2[,i],iris2[,j],n=21)
    
e[[i]] <- d

使用占位符分配所需的空间量并将项目放入该空间而不是使用rbindcbind 也是一个好主意。

【讨论】:

感谢您的建议。没想到这种方式,效果很好。但问题是我正在运行的实际数据有 100 多列,运行代码似乎需要 20 多分钟......我只是想看看数据与所有其他数据的滚动相关性,正如我简要介绍的在我的问题中提到。有什么方法可以提高效率吗?再次感谢。 @sh2657 你的评论好像被删了。 对不起,我不小心按了 Enter 并正在编辑它。现在应该好了。 @sh2657 如果要计算 100 列的相关性,100 次可能需要一段时间。如上所述使用foreachmapply 会有所帮助,但仍需要一点时间。 应该检查一下。感谢您的帮助。【参考方案2】:

虽然不是在 R 中动态创建数据框的好习惯(您应该像其他答案一样将它们放在列表中),但这样做的方法是使用 @ 987654321@ 和 get 函数。

for (i in 1:ncol(iris2))  
   for (j in 1:ncol(iris2))
      c <-  runCor(iris2[,i],iris2[,j],n=21)

      # Assign 'c' to the name df1, df2...
      assign(paste0("df", i), c)
      


# to have access to the dataframe:
get("df1")

# or inside a loop
get(paste0("df", i))

【讨论】:

【参考方案3】:

既然您说您的计算速度很慢,我想为您提供一个并行解决方案。如果您有一台现代计算机,它可能有 2 个内核,如果不是 4 个(或更多!)。您可以通过以下方式轻松检查:

require(parallel) # for parallelization
detectCores()

现在是代码:

require(quantmod)
require(TTR)

iris2 <- iris[,1:4]

并行化需要将函数和变量放入一个特殊的环境中,该环境随每个进程创建和销毁。这意味着必须创建一个包装函数来定义变量和函数。

wrapper <- function(data, n) 
  # variables placed into environment
  force(data)
  force(n)

  # functions placed into environment
  # same inner loop written in earlier answer
  runcor <- function(data, n, i) 
    d <- matrix(0, nrow = length(data[,1]), ncol = length(data[1,]))
    for (j in 1:ncol(data)) 
      d[,i] <- TTR::runCor(data[,i], data[,j], n = n)
    
    return(d)
  

  # call function to loop over iterator i
  worker <- function(i) 
    runcor(data, n, i)
  

  return(worker)

现在在您的本地计算机上创建一个集群。这允许多个内核单独运行。

parallelcluster <- makeCluster(parallel::detectCores())
models <- parallel::parLapply(parallelcluster, 1:ncol(iris2),
                              wrapper(data = iris2, n = 21))
stopCluster(parallelcluster)

完成后停止并关闭集群。

【讨论】:

你是最棒的。谢谢。

以上是关于如何将来自for循环的数据存储在for循环内? (r中的滚动相关)的主要内容,如果未能解决你的问题,请参考以下文章

存储来自三重 for 循环的数据

如何访问for循环外的值

来自 for 循环内的 AJAX 链中最后一个 AJAX 请求的返回值

如何使用 for 循环将第一次使用日期存储在字典中

使用 AsyncTask 的结果在其 onPostExecute 内运行 for 循环(再次异步)

如何在 Django 模板语言中正确构建 for 循环