【问题标题】:How to use plyr mdply with failsafe execution in parallel如何将 plyr mdply 与故障安全执行并行使用
【发布时间】:2013-06-24 11:16:02
【问题描述】:

我必须对多个数据集进行分析。我使用 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)

【问题讨论】:

  • 你也可以用try代替tryCatch;它更简单,通常可以满足所有要求。

标签: r parallel-processing plyr


【解决方案1】:

函数mdply.anyfun.parallel.failsafe 接受data.frame 和函数名myfunction(作为字符)作为参数。然后为 data.frame 中的每一行调用myfunction,并将所有列值作为参数传递,就像原始 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 不起作用会很有趣。

【讨论】:

  • 这是您自己问题的答案吗?如果是,我建议您添加几行解释关键部分是什么。否则,您的答案对其他人没有帮助。但是,如果这只是为上述问题提供了额外的信息,我建议您减少代码量并将剩余内容放在问题正文中。
  • @Thilo 建议采纳。示例缩短。我发布它是因为我认为这是一个常见问题,这已经困扰了我一段时间......但如果我的解决方案不被理解,那么发布它是没有意义的。我希望它现在变得更清楚。感谢您的评论。
  • 太棒了!这就是我希望看到的。将 -1 更改为 +1 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多