2

我必须对多个数据集进行分析。我使用 plyr (mdply) 和 doSNOW 包来使用多个内核。有时分析代码会失败,引发错误并停止执行。我希望继续对其他数据集进行分析。如何做到这一点?解决方案 1:编码以便捕获所有不可行的错误。解决方案 2:一个故障安全 plyr 包装器,用于并行运行返回所有有效结果的函数,并指出哪里出了问题。

我实施了第二个解决方案(见下面的答案)。棘手的部分是我想要一个函数调用来完成故障安全和返回数据帧功能。

我是如何构造函数的:实际的函数调用用tryCatch. 它是从callfailsafe函数内部调用的,这反过来又需要将单个函数名称 simple和相应的参数(...)传递给整个过程。也许我做得太复杂了……但它确实有效。

确保您的simple函数不依赖于任何全局定义的函数或参数,因为在与 .parallel=T 和 doSNOW 一起使用时不会加载这些函数或参数。

这是我的测试数据集:有 100 个任务。对于每个“简单”函数将被调用。但是有时该功能会失败。我通常在自动加载许多 rdata 文件进行大量处理、保存一些输出并最终返回 data.frame 对象的任务上使用它。

library(plyr)
library(doSNOW)
N=100
multiargtab= data.frame(ID=1:N,A=round(runif(N,0,1)),B=round(runif(N,0,1)))

simple=function(ID,A,B){ # a function that will sometimes fail
  if(B==0) rm(B)
  data.frame(A=A,B=B,AB=A/B,ID=ID)
}

调用函数的签名是:

res2=mdply.anyfun.parallel.failsafe(multiargtab,simple)
4

1 回答 1

3

该函数mdply.anyfun.parallel.failsafe接受一个data.frame和一个函数名myfunction(作为字符)作为参数。myfunction然后为 data.frame 中的每一行调用并将所有列值作为参数传递,就像原始 mdply 一样。除了原始mdply功能之外,该功能不会在任务失败时停止,而是继续执行其他任务。失败任务的错误信息在“error”列中返回。

library(doSNOW)
library(plyr)
mdply.anyfun.parallel.failsafe=function(multiargtab,myfunction){
  cl<-makeCluster(4)
  registerDoSNOW(cl)

  callfailsafe=function(...){
    r=tryCatch.W.E(FUN(...))
    val=r$value[[1]]
    if(!"simpleError" %in% class(val)){
      return(val)
    }else{
      return(data.frame(...,error= (as.character(val))))
    }
  }

  tryCatch.W.E=function(expr) {
    #pass a function, it will be run and result returned; if error then error will return - BUT function will not fail
    W <- NULL
    w.handler <- function(w){ # warning handler
      W <<- w
      invokeRestart("muffleWarning")
    }
    list(value = list(withCallingHandlers(tryCatch(expr, error = function(e) e),  warning = w.handler)), warning = W)
  }
  FUN=match.fun(myfunction)
  res=mdply(multiargtab,callfailsafe,.parallel=T)
  stopCluster(cl)
  res
}

测试功能:

res2=mdply.anyfun.parallel.failsafe(multiargtab,simple)

这通常工作正常。当 multiargtab 是类型时,我只有一些奇怪的错误data.table

Error in data.table(..., key = key(..1)) : 
  Item 1 has no length. Provide at least one item

我通过转换为 ... 来规避错误,as.data.frame尽管知道为什么 data.table 不起作用会很有趣。

于 2013-06-24T11:16:02.357 回答