11

这个问题可能会或可能不会受到我失去整个 3 小时地理编码运行的启发,因为其中一个值返回了错误。提示遗憾(向下)投票。

基本上在由sapply. 我继续了options(error=recover),但尽管浏览了我可用的每个级别,但我找不到任何地方将(数千次成功)调用 FUN 的结果存储在内存中。

我在浏览时发现的一些对象在我尝试检查它们时出错,声称这些引用不再有效。不幸的是,我丢失了特定的错误消息。

这是一个简单的示例,虽然它没有复制参考错误(我怀疑这与消失的环境有关并且可能无关紧要),但确实表明我看不到保存已处理数据的方法。

有这样的技术吗?

请注意,我已经意识到我的错误并插入了比以前更强大的错误处理 via try,但我正在寻找一种事后而不是事前恢复内容的方法。

测试功能

sapply( seq(10), function(x) {
  if(x==5) stop("Error!")
  return( "important data" )
} )

互动探索

> sapply( seq(10), function(x) {
+   if(x==5) stop("Error!")
+   return( "important data" )
+ } )
Error in FUN(1:10[[5L]], ...) : Error!

Enter a frame number, or 0 to exit   

1: sapply(seq(10), function(x) {
    if (x == 5) 
        stop("Error!")
    return("important data")
})
2: lapply(X = X, FUN = FUN, ...)
3: FUN(1:10[[5]], ...)

Selection: 3
Called from: FUN(1:10[[5L]], ...)
Browse[1]> ls()
[1] "x"
Browse[1]> x
[1] 5
Browse[1]> 
Enter a frame number, or 0 to exit   

1: sapply(seq(10), function(x) {
    if (x == 5) 
        stop("Error!")
    return("important data")
})
2: lapply(X = X, FUN = FUN, ...)
3: FUN(1:10[[5]], ...)

Selection: 2
Called from: lapply(X = X, FUN = FUN, ...)
Browse[1]> ls()
[1] "FUN" "X"  
Browse[1]> X
 [1]  1  2  3  4  5  6  7  8  9 10
Browse[1]> FUN
function(x) {
  if(x==5) stop("Error!")
  return( "important data" )
}
Browse[1]> 
Enter a frame number, or 0 to exit   

1: sapply(seq(10), function(x) {
    if (x == 5) 
        stop("Error!")
    return("important data")
})
2: lapply(X = X, FUN = FUN, ...)
3: FUN(1:10[[5]], ...)

Selection: 1
Called from: sapply(seq(10), function(x) {
    if (x == 5) 
        stop("Error!")
    return("important data")
})
Browse[1]> ls()
[1] "FUN"       "simplify"  "USE.NAMES" "X"        
Browse[1]> X
 [1]  1  2  3  4  5  6  7  8  9 10
Browse[1]> USE.NAMES
[1] TRUE
Browse[1]> simplify
[1] TRUE
Browse[1]> FUN
function(x) {
  if(x==5) stop("Error!")
  return( "important data" )
}
Browser[1]> Q

需要明确的是,我希望找到的是向量:

[1] "important data" "important data" "important data" "important data"

也就是说,到此为止已经完成的内部循环的结果。

编辑:使用 C 代码更新

里面.Internal(lapply())以下代码

PROTECT(ans = allocVector(VECSXP, n));
...
for(i = 0; i < n; i++) {
   ...
   tmp = eval(R_fcall, rho);
   ...
   SET_VECTOR_ELT(ans, i, tmp);
}

ans当任何呼叫lapply失败时,我想知道。

4

3 回答 3

4

我很难理解为什么try()这里不是要走的路?如果由于sapply()某种原因失败了,那么你

  1. 想要很好地处理失败
  2. 从那里继续

为什么您希望整个数据分析/处理步骤仅因错误而停止?这似乎是你所提议的。与其尝试恢复已经完成的工作,不如编写代码使其继续运行,记录发生的错误,同时优雅地进入流程的下一步。

这有点令人费解,因为您给出的示例是人为的(如果您知道什么会导致错误,您可以在没有 的情况下处理该错误try()),但请耐心等待:

foo <- function(x) {
    res <- try({
        if(x==5) {
            stop("Error!")
        } else {
            "important data"
        }
    })
    if(inherits(res, "try-error"))
        res <- "error occurred"
    res
}

> sapply( seq(10), foo)
Error in try({ : Error!
 [1] "important data" "important data" "important data" "important data"
 [5] "error occurred" "important data" "important data" "important data"
 [9] "important data" "important data"

在后台运行需要数周才能在我的工作站上完成的作业后,我很快学会了try()围绕单个语句而不是大块代码编写大量调用,这样一旦发生错误,我就可以快速退出迭代/步骤对正在运行的工作影响最小;换句话说,如果一个特定的 R 调用失败,我返回的东西可以sapply()很好地插入(或任何函数)返回的对象中。

对于更复杂的事情,我可能会使用lapply()

foo2 <- function(x) {
    res <- try({
        if(x==5) {
            stop("Error!")
        } else {
            lm(rnorm(10) ~ runif(10))
        }
    })
    if(inherits(res, "try-error"))
        res <- "error occurred"
    res
}

out <- lapply(seq(10), foo2)
str(out, max = 1)

因为您将需要列表,而不是尝试将更复杂的对象简化为简单的东西:

>     out <- lapply(seq(10), foo2)
Error in try({ : Error!
> str(out, max = 1)
List of 10
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ : chr "error occurred"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"
 $ :List of 12
  ..- attr(*, "class")= chr "lm"

也就是说,我可能会通过一个for()循环来完成此操作,在我迭代时填写一个预先分配的列表。

于 2012-10-22T11:35:13.477 回答
1

也许我不明白,这肯定会减慢您的速度,但是每次全局分配呢?

safety <- vector()
sapply( seq(10), function(x) {
  if(x==5) stop("Error!")
  assign('safety', c(safety, x), envir = .GlobalEnv)
  return( "important data" )
} )

产量:

> safety <- vector()
> sapply( seq(10), function(x) {
+   if(x==5) stop("Error!")
+   assign('safety', c(safety, x), envir = .GlobalEnv)
+   return( "important data" )
+ } )
Error in FUN(1:10[[5L]], ...) : Error!
> safety
[1] 1 2 3 4
于 2012-10-22T02:26:08.603 回答
1

您从未将中间值分配给任何东西。我不明白你为什么认为应该有任何神圣的内脏。您需要以某种方式记录值:

 res <- sapply( seq(10), function(x) { z <- x
                                   on.exit(res <<- x);
                                   if(x==5) stop("Error!")
 } )
Error in FUN(1:10[[5L]], ...) : Error!
 res
#[1] 5

on.exit方法在?par页面上进行了说明,作为在绘图出错时恢复标准设置的一种方法。(我无法让它与on.exit(res <- x).

于 2012-10-22T01:30:05.023 回答