【问题标题】:plyr parallel error-handling and warningsplyr 并行错误处理和警告
【发布时间】:2015-02-16 10:45:44
【问题描述】:

这是我用于错误处理的常见结构:

x <- tryCatch(foo(), error=function(e){
    warning(e)
    NULL})

我对大量数据对象运行 foo,其中一些可能由于某种原因而失败,如果是这样,我希望结果为 NULL,这样我的整个运行就不会停止,但我也希望得到警告,所以我可以看到失败的原因和原因。

我经常像这样从 plyr 运行这些,假设其中一些失败:

x <- llply(1:4, .fun=function(i) {  
    result<-tryCatch({
        if(i %% 2==0) stop(i)
        i}, error=function(e) {
           warning(e)
           NULL})
    result})
 x

结果:

 Warning messages:
 1: In doTryCatch(return(expr), name, parentenv, handler) : 2
 2: In doTryCatch(return(expr), name, parentenv, handler) : 4

 > x
 [[1]]
 [1] 1

 [[2]]
 NULL

 [[3]]
 [1] 3

 [[4]]
 NULL

但是,假设我使用相同的代码打开并行计算。

 require(doParallel)
 registerDoParallel(cores=4)
 x <- llply(1:4, .parallel=TRUE, .fun=function(i) {  
      result<-tryCatch({
          if(i %% 2==0) stop(i)
          i}, error=function(e) {
              warning(e)
              NULL})
      result})

  Result: 
  Error in do.ply(i) : task 2 failed - "2"

作业因任何任务中的错误而失败,并且没有构造任何结果。警告(e)以某种方式转换为错误。我可以通过注释掉警告(e)来解决这个问题,然后当出现错误时,我会在我的数据结构中获得所需的 NULL 结果,但随后我会丢失有关所发生情况的信息。

事实上,我不知道从并行 plyr 抛出警告的任何好方法。他们似乎被压制了。如果这是并行性的限制,那是有道理的。但我认为警告变成错误行为很奇怪,我想了解这里发生了什么。

【问题讨论】:

    标签: r error-handling parallel-processing try-catch plyr


    【解决方案1】:

    在我看来,warning 函数在使用 simpleError 对象调用时有问题。它似乎工作正常:

    > warning(simpleError(1))
    Warning message:
    1 
    

    但奇怪的是,当在 tryCatch 内部调用时,警告被视为错误:

    > tryCatch({
    +   warning(simpleError(1))
    + }, error=function(e) {
    +   cat('caught an error\n')
    +   print(class(e))
    +   print(e)
    + })
    caught an error
    [1] "simpleError" "error"       "condition"  
    <simpleError: 1>
    

    由于foreach 包评估tryCatch 中的循环体,它认为发生了错误。例如:

    > library(foreach)
    > foreach(i=1:4) %do% warning(simpleError(1))
    Error in warning(simpleError(1)) : task 1 failed - "1"
    

    这意味着通过.paropts 选项将.errorhandling='pass' 选项传递给foreach 应该可以防止错误中止llply

    > x <- llply(1:4, .parallel=TRUE, .paropts=list(.errorhandling='pass'),
    +       .fun=function(i) {
    +       result<-tryCatch({
    +           if(i %% 2==0) stop(i)
    +           i}, error=function(e) {
    +               warning(e)
    +               NULL})
    +       result})
    > x
    [[1]]
    [1] 1
    
    [[2]]
    <simpleError in doTryCatch(return(expr), name, parentenv, handler): 2>
    
    [[3]]
    [1] 3
    
    [[4]]
    <simpleError in doTryCatch(return(expr), name, parentenv, handler): 4>
    

    看起来你可以通过在调用warning之前将simpleError对象的类更改为simpleWarning来解决这个问题:

    x <- llply(1:4, .parallel=TRUE,
          .fun=function(i) {
          result<-tryCatch({
              if(i %% 2==0) stop(i)
              i}, error=function(e) {
                  class(e) <- class(simpleWarning(''))
                  warning(e)
                  NULL})
          result})
    

    如果您想在顺序或并行运行时获得警告,您可以将错误对象转换为警告对象并将它们与其他结果一起返回。例如:

    x <- llply(1:4, .parallel=TRUE, .fun=function(i) {
             result<-tryCatch({
                 if(i %% 2==0) stop(i)
                 i}, error=function(e) {
                    class(e) <- class(simpleWarning(''))
                    e})
             result})
    
    for (i in seq_along(x)) {
        if (inherits(x[[i]], 'simpleWarning')) {
            warning(x[[i]])
            x[i] <- list(NULL)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-24
      • 2018-08-06
      • 2010-12-20
      • 1970-01-01
      • 2019-02-04
      相关资源
      最近更新 更多