【问题标题】:How to store data from for loop inside of for loop? (rolling correlation in r)如何将来自for循环的数据存储在for循环内? (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 绝不是一个好主意。使用具有预定义长度的列表以避免在内存中过度复制是更好的做法。

标签: r loops lapply datastore


【解决方案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)
    

    完成后停止并关闭集群。

    【讨论】:

    • 你是最棒的。谢谢。
    猜你喜欢
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 2021-10-28
    • 2021-07-28
    • 1970-01-01
    • 2021-08-17
    • 2017-07-27
    相关资源
    最近更新 更多