Как сказать lapply игнорировать ошибку и обрабатывать следующую вещь в списке? - PullRequest
32 голосов
/ 07 апреля 2010

Ниже приведен пример функции, которая считывает дату в виде строки и возвращает ее как объект даты. Если он читает строку, которую он не может преобразовать в дату, он возвращает ошибку.

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)

Я предполагаю, что мне нужна попытка перехвата, но есть ли способ отловить ошибку для строки "foo", в то же время попросив lapply продолжить и прочитать третью дату?

Ответы [ 3 ]

54 голосов
/ 07 апреля 2010

Используйте выражение 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"
7 голосов
/ 07 апреля 2010

Можно попытаться сделать это проще, а не усложнять:

  • Использовать векторизованный разбор даты
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() к вашему разбору даты.

Все это немного странно, когда вы переходите от однотипной структуры данных (вектор символов) к чему-то другому, но вы не можете легко смешивать типы, если не храните их в list тип.Так что, возможно, вам нужно переосмыслить это.

0 голосов
/ 07 апреля 2010

Предполагая, что 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"
...