0

我正在尝试从 ade4 包中执行函数 varipart()。我正在尝试在同一函数的不同部分中的每个列表中使用相同的数字数据框。我需要为每组数据框传递这个。

########### DATA BELOW
    d1 <- data.frame(y1 = c(1, 2, 3), y2 = c(4, 5, 6))
      d2 <- data.frame(y1 = c(3, 2, 1), y2 = c(6, 5, 4))
      d3 <- data.frame(y1 = c(2, 1, 2), y2 = c(5, 6, 4))
      spec.list <- list(d1, d2, d3)

      d1 <- data.frame(y1 = c(20, 87, 39), y2 = c(46, 51, 8))
      d2 <- data.frame(y1 = c(30, 21, 12), y2 = c(61, 51, 33))
      d3 <- data.frame(y1 = c(2, 11, 14), y2 = c(52, 16, 1))
      env.list <- list(d1, d2, d3)

      d1 <- data.frame(y1 = c(0.15, 0.1, 0.9), y2 = c(0.46, 0.51, 0.82))
      d2 <- data.frame(y1 = c(0.13, 0.31, 0.9), y2 = c(0.11, 0.51, 0.38))
      d3 <- data.frame(y1 = c(0.52, 0.11, 0.14), y2 = c(0.52, 0.36, 0.11))
      spat.list <- list(d1, d2, d3)
###############
      # I have tried two ways 
      library(parallel)
      library(ade4)

        output_varpart <- mclapply(spec.list, function(x){
          varipart(x, env.list, spat.list, type = "parametric")
        })

        output_varpart <- mclapply(x, function(x){
          varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
        })

        for(i in 1:length(x)){
          results <- varipart(spec.list, env.list, spat.list, type = "parametric")
        }

这些方法都不起作用!请温柔,我是列表语法和循环的新手。错误分别是“警告消息:在 mclapply(output.spectrans.dudi, function(x) { :所有计划的核心在用户代码中遇到错误”和“x * w 中的错误:二进制运算符的非数字参数”。

4

1 回答 1

1

你很亲密,但我会解释一下lapply(和mclapply)是如何工作的,因为感觉就像你在混淆角色x是什么。首先,这应该有效:

output_varpart <- mclapply(1:3, function(x){
      varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
    })

但为什么?
函数lapply意味着:将函数(第二个参数)应用于列表中的所有值(第一个参数)。所以lapply(list('Hello', 'World', '!'), print)会做

print('Hello')
print('World')
print('!')

它将返回一个长度为 3 的列表和结果(返回的print是打印的值)

但很多时候,没有一种功能可以完全满足您的需求。您始终可以定义一个函数,如下所示:

my_vari_fun <- function(index) {
  varipart(spec.list[[index]], env.list[[index]], spat.list[[index]], type = "parametric")
}

然后,您可以将其称为 like ,并且该参数是否称为or或其他名称都my_vari_fun(1)无关紧要。我确定你明白了。所以下一步将是xindex

output_varpart <- lapply(list(1,2,3), my_vari_part)

这样做的缺点是需要多行代码,我们可能不会再使用my_vari_fun了。所以这就是我们可以提供匿名函数的原因,我们只是给 lapply 一个函数而不给它分配一个名字。我们只是my_vari_fun用它的“值”(恰好是一个函数)替换它。

但是,在这个功能之外,x没有任何意义。我们也可以称它为任何其他名称。

我们只需要告诉 lapply 输入什么值:list(1,2,3)。或者更简单的向量,lapply它将转换:1:3

顺便说一句,我刚刚3在此处插入,但对于您可以使用的一般情况1:length(spec.list),您只需确保所有列表的长度相同。

最后,我现在谈到了lapply,但对于mclapply. 区别仅在引擎盖下,mclapply会将其工作分散到多个内核上。

编辑:调试

lapply在调试中,和之间有更多的区别mclapply。我先讲讲lapply

如果您的代码中有一些错误在 内部执行lapply,则整个代码lapply将失败,并且不会分配任何内容。这有时会让人很难准确地发现错误发生的位置,但这是可以做到的。一个简单的解决方法可能是lapply只提供部分输入,以查看它在哪里中断。
但是 R 也带有一些调试工具,一旦遇到错误,执行就会冻结。我找到recover了最有用的工具。

您可以设置它options(error=recover),每次遇到错误时,它都会为您提供抛出错误的函数的向后列表,它被哪个函数调用,被哪个函数调用,......
然后你可以选择一个number 来探索该函数运行的环境。当我尝试模仿您的错误时,我得到了这个:

Error in x * w : non-numeric argument to binary operator

Enter a frame number, or 0 to exit   

 1: source("~/.active-rstudio-document")
 2: withVisible(eval(ei, envir))
 3: eval(ei, envir)
 4: eval(ei, envir)
 5: .active-rstudio-document#20: lapply(1:3, function(x) {
    varipart(spec.list[[x]], env.list[[x]], spat.list[
 6: FUN(X[[i]], ...)
 7: .active-rstudio-document#21: varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
 8: as.matrix(scalewt(Y, scale = scale))
 9: scalewt(Y, scale = scale)
10: apply(df, 2, weighted.mean, w = wt)
11: FUN(newX[, i], ...)
12: weighted.mean.default(newX[, i], ...)

其中很多是 R 的内部函数,你可以看到它做了什么varipart:它将东西传递给较低的函数,由谁传递等等。

出于我们的目的,我们需要数字 6:这里lapply调用您的函数,并带有i-th输入值。
一旦我们输入6,我们就会得到一个新的提示,上面写着Browse[1]>(在某些情况下它可能是另一个数字),我们在环境中,就好像我们刚刚输入了我们的

function(x){
  varipart(spec.list[[x]], env.list[[x]], spat.list[[x]], type = "parametric")
}

这意味着打字x会给你这个函数失败的值,spec.list[[x]]等等会告诉你哪些输入varipart失败。然后最后一步是决定这意味着什么:要么varipart坏了,要么你的输入之一坏了。

data.frame在这种情况下,我注意到我可以通过将其中一列放在else then中来得到相同的错误numeric。但是你必须看看这是否也是你的问题,但是如果你弄清楚问题出在哪里,调试就会变得容易得多。

与 mclapply

mclapply在多个核心上运行,这意味着如果一个核心出现错误,其他核心仍然可以完成它们的工作。

对于分叉进程遇到错误的计算,该错误将是返回值,以try-error-object 的形式。但请注意,同一核心的其他迭代也是如此。所以如果 for mclapply(1:10, fun),fun(1)会抛出一个错误,在 2 个内核的情况下,所有奇数输入都会显示该错误。

所以我们可以查看返回值,缩小搜索范围:

sapply(output_varpart, class)

错误出现在输出类为 try-error 的迭代中,但我们无法确切知道是哪一个。

如何实际解决它取决于计算的大小。
如果它们真的很广泛,那么保留确实成功的值并通过仅重新运行失败的部分来再次缩小范围可能是值得的。或者如果我只看到一个try-error,我们就不需要再看下去了。
但通常,我发现将 更改mclapply为常规lapply并使用上述方法最有用。

于 2018-12-13T03:00:43.747 回答