【问题标题】:Nested foreach loop in R where inner loop returns a matrixR中的嵌套foreach循环,其中内部循环返回一个矩阵
【发布时间】:2015-04-26 13:24:45
【问题描述】:

我正在尝试并行化我拥有的 for 循环。有问题的循环中有一个嵌套循环,我想并行化。答案肯定与:nested foreach loops in R to update common array 非常相似,但我似乎无法让它工作。我已经尝试了所有我能想到的选项,包括将内部循环变成它自己的函数并将其并行化,但我不断得到空列表。

第一个非 foreach 示例有效:

theFrame <- data.frame(col1=rnorm(100), col2=rnorm(100))

theVector <- 2:30

regFor <- function(dataFrame, aVector, iterations)
{   
    #set up a blank results matrix to save into.
    results <- matrix(nrow=iterations, ncol=length(aVector))

    for(i in 1:iterations)
    {
        #set up a blank road map to fill with 1s according to desired parameters
        roadMap <- matrix(ncol=dim(dataFrame)[1], nrow=length(aVector), 0)
        row.names(roadMap) <- aVector
        colnames(roadMap) <- 1:dim(dataFrame)[1]

        for(j in 1:length(aVector))
        {
            #sample some of the 0s and convert to 1s according to desired number of sample
            roadMap[j,][sample(colnames(roadMap),aVector[j])] <- 1
        }

        temp <- apply(roadMap, 1, sum)

        results[i,] <- temp
    }

    results <- as.data.frame(results)
    names(results) <- aVector

    results
}

test <- regFor(theFrame, theVector, 2)

但是这个和我的其他类似尝试都行不通。

trying <- function(dataFrame, aVector, iterations, cores)
{   
    registerDoMC(cores)

    #set up a blank results list to save into. i doubt i need to do this
    results <- list()

    foreach(i = 1:iterations, .combine="rbind") %dopar%
    {
        #set up a blank road map to fill with 1s according to desired parameters
        roadMap <- matrix(ncol=dim(dataFrame)[1], nrow=length(aVector), 0)
        row.names(roadMap) <- aVector
        colnames(roadMap) <- 1:dim(dataFrame)[1]

        foreach(j = 1:length(aVector)) %do%
        {
            #sample some of the 0s and convert to 1s according to desired number of sample
            roadMap[j,][sample(colnames(roadMap),aVector[j])] <- 1
        }

        results[[i]] <- apply(roadMap, 1, sum)
    }
    results
}

test2 <- trying(theFrame, theVector, 2, 2)

我认为无论如何我都必须在内循环上使用 foreach ,对吗?

【问题讨论】:

    标签: r loops foreach parallel-processing domc


    【解决方案1】:

    使用 foreach 时,您绝不会像您所怀疑的那样“设置一个空白的结果列表来保存”。相反,您组合了评估 foreach 循环体的结果,并返回该组合结果。在这种情况下,我们希望外部 foreach 循环将向量(由内部 foreach 循环计算)按行组合成一个矩阵。该矩阵分配给变量results,然后将其转换为数据框。

    这是我第一次尝试转换您的示例:

    library(doMC)
    
    foreachVersion <- function(dataFrame, aVector, iterations, cores) {
      registerDoMC(cores) # unusual, but reasonable with doMC
      rows <- nrow(dataFrame)
      cols <- length(aVector)
      results <-
        foreach(i=1:iterations, .combine='rbind') %dopar% {
          # The value of the inner foreach loop is returned as
          # the value of the body of the outer foreach loop
          foreach(aElem=aVector, .combine='c') %do% {
            roadMapRow <- double(length=rows)
            roadMapRow[sample(rows,aElem)] <- 1
            sum(roadMapRow)
          }     
        }
      results <- as.data.frame(results)
      names(results) <- aVector
      results
    }
    

    内部循环不需要实现为 foreach 循环。您也可以使用sapply,但我会尝试找出是否有更快的方法。但是对于这个答案,我想演示一个 foreach 方法。我使用的唯一真正优化是通过在内部 foreach 循环中执行 sum 来摆脱对 apply 的调用。

    【讨论】:

    • 谢谢!这很好用。如果不清楚,我的实际代码在两个循环中都在做更复杂的事情,所以使用 sapply 等可能会非常棘手。我最初的配方有两个主要问题。第一个是设置一个空白列表并尝试将结果保存到其中(顺便说一下,我在其他情况下使用 foreach 成功地做到了这一点),第二个是没有掌握 .combine 正在做什么的含义。这很酷,并且无需使用像 Reduce() 之类的东西就可以产生结果,我过去使用 foreach 已经完成了这些。谢谢!
    • @forlooper 在 foreach 循环中可能会产生副作用,但根据您使用的后端,它的工作方式会有所不同,因此强烈建议不要这样做。本来想在foreach中防止出现副作用的可能性,但最终还是放弃了尝试。
    • 谢谢史蒂夫。我想我应该重新编程一些东西!
    【解决方案2】:

    你需要将 foreach 的结果放入一个变量中:

        results<- foreach( ...
    

    【讨论】:

    • 这是问题的症结所在。谢谢!上面史蒂夫韦斯顿的回答是对这个问题的完整回答。
    • 对不起,我第一次点击了错误的符号。我现在修好了。再次感谢。
    【解决方案3】:
    • 我知道这是一个过时的问题,但只是为了给那些提示 谁没有嵌套 foreach 工作。
    • 如果用 foreach()%dopar%{foreach()%do%{}} 并行化外循环,你会 需要在外部的扩充中包含.packages = c("doSNOW") 循环,否则会遇到"doSNOW not found" 错误。
    • 一般来说,人们只是并行化内循环(foreach()%:%foreach()%dopar%{},论坛上也有建议),这 对于大量数据可能会慢得多(等待组合 每 100 个结果以及每个内部循环结束时,此过程不是并行的!)。

    【讨论】:

      猜你喜欢
      • 2018-07-15
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2019-07-13
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      相关资源
      最近更新 更多