如何告诉lapply忽略错误并处理列表中的下一项?

48

我有一个示例函数,可以将日期字符串读入并将其作为日期对象返回。如果它读取的字符串无法转换为日期,则返回一个错误。

testFunction <- function (date_in) {
    return(as.Date(date_in))
    }

testFunction("2010-04-06")  # this works fine
testFunction("foo")  # this returns an error

现在,我想使用lapply函数并将其应用于一组日期:

dates1 = c("2010-04-06", "2010-04-07", "2010-04-08")
lapply(dates1, testFunction)  # this works fine

但是,如果我想在一个列表上应用该函数,当两个良好日期之间的一个字符串返回错误时,最好的处理方法是什么?

dates2 = c("2010-04-06", "foo", "2010-04-08")
lapply(dates2, testFunction)

我假设我需要在那里使用try catch,但是是否有一种方法可以捕获"foo"字符串的错误,同时请求lapply继续并读取第三个日期?


1
非常相关:https://dev59.com/dHM_5IYBdhLWcg3wZSPX - Shane
4个回答

78

在该函数周围使用tryCatch表达式,以处理可能引发的错误消息:

testFunction <- function (date_in) {
  return(tryCatch(as.Date(date_in), error=function(e) NULL))
}

tryCatch函数的好处在于,您可以决定在出现错误时该怎么做(在这种情况下,返回NULL)。

> lapply(dates2, testFunction)
[[1]]
[1] "2010-04-06"

[[2]]
NULL

[[3]]
[1] "2010-04-08"

1
是的,在这种情况下确实如此。但是,如果问题是泛化的,那么使用tryCatch可能是继续处理lapply中的错误的最佳方法。我认为日期示例只是一个例子? - Shane
谢谢Dirk和Shane,实际上异常处理就是我想要的。日期只是更复杂函数的一个示例,但这是我能想到的从一堆东西中返回错误的最简单的事情。 - John
4
另外,plyr 包中的 failwith 函数可以自动化执行这个常见任务。 - hadley
1
另一种可能性是在lapply中添加tryCatch,并像往常一样让函数引发错误。lapply(dates2, function(x) tryCatch(testFunctionWihoutTryCatch(x), error=function(e) NULL))。当然,Dirk的评论在这个特定的情况下非常有道理。 - DJJ
我在思考这个想法,并提出了这个 - DJJ
显示剩余2条评论

8

相比于让它变得复杂,我们可以尝试保持简单:

  • 使用向量化日期解析
R> as.Date( c("2010-04-06", "foo", "2010-04-08") )
[1] "2010-04-06" NA           "2010-04-08"
您可以轻松地将 na.omit() 或其他内容包装在其周围。或者从初始向量中找到NA的索引并相应地提取,或使用NA的补集来查找解析的日期,等等。所有这些都已经在这里了。
  • 您可以使您的 testFunction() 做一些事情。在那里使用测试 -- 如果返回的(解析的)日期为NA,则执行某些操作。

  • tryCatch() 块或 try() 添加到日期解析中。

整个过程有点奇怪,因为您从一个单一类型的数据结构(字符向量)转移到其他类型,但除非将它们保留在列表类型中,否则您不能轻松混合类型。所以也许您需要重新考虑这个问题。


7

您还可以使用purrr帮助函数mappossibly来完成此类任务。例如:

library(purrr)
map(dates2, possibly(testFunction, NA))

这里的possibly将会返回NA(或者你指定的其他错误值)。


0
假设testFunction()不是简单的和/或者无法更改它,那么可以将其包装在自己的函数中,并使用tryCatch()块。例如:
> FaultTolerantTestFunction <- function(date_in) {
+    tryCatch({ret <- testFunction(date_in);}, error = function(e) {ret <<- NA});
+    ret
+ }
> FaultTolerantTestFunction('bozo')
[1] NA
> FaultTolerantTestFunction('2010-03-21')
[1] "2010-03-21"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接