Есть ли у кого-нибудь примеры / руководства по обработке исключений в R? Официальная документация очень краткая.
Есть ли у кого-нибудь примеры / руководства по обработке исключений в R? Официальная документация очень краткая.
Ответы:
Помимо ответа Шейна, указывающего на другие обсуждения StackOverflow, вы можете попробовать функцию поиска кода. Этот исходный ответ указывал на поиск кода Google, который с тех пор был прекращен, но вы можете попробовать
Просто для записи, есть также, try
но tryCatch
может быть предпочтительнее. Я попробовал быстро подсчитать в Google Code Search, но попытка дает слишком много ложных срабатываний для самого глагола - но, похоже, tryCatch
он более широко используется.
В основном вы хотите использовать tryCatch()
функцию. См. Справку ("tryCatch") для получения дополнительных сведений.
Вот тривиальный пример (учтите, что с ошибкой можно делать все, что угодно):
vari <- 1
tryCatch(print("passes"), error = function(e) print(vari), finally=print("finished"))
tryCatch(stop("fails"), error = function(e) print(vari), finally=print("finished"))
Взгляните на эти связанные вопросы:
Мне помог этот результат поиска в Google: http://biocodenv.com/wordpress/?p=15 .
for(i in 1:16){
result <- try(nonlinear_modeling(i));
if(class(result) == "try-error") next;
}
Функция trycatch()
довольно проста, и по ней есть много хороших руководств. Отличное объяснение обработки в R ошибок можно найти в книге Hadley Уикхемы Advanced-R , а также то , что следует , является очень основным интро withCallingHandlers()
и withRestarts()
в нескольких слов , как это возможно:
Допустим, программист низкого уровня пишет функцию для вычисления абсолютного значения. Он не знает, как это вычислить, но умеет конструировать ошибку и старательно передает свою наивность:
low_level_ABS <- function(x){
if(x<0){
#construct an error
negative_value_error <- structure(
# with class `negative_value`
class = c("negative_value","error", "condition"),
list(message = "Not Sure what to with a negative value",
call = sys.call(),
# and include the offending parameter in the error object
x=x))
# raise the error
stop(negative_value_error)
}
cat("Returning from low_level_ABS()\n")
return(x)
}
Программист среднего уровня также пишет функцию для вычисления абсолютного значения, используя крайне неполную low_level_ABS
функцию. Он знает, что код низкого уровня выдает negative_value
ошибку, когда значение x
отрицательное, и предлагает решение проблемы, устанавливая, restart
что позволяет пользователям mid_level_ABS
контролировать способ mid_level_ABS
восстановления (или отказа) от negative_value
ошибки.
mid_level_ABS <- function(y){
abs_y <- withRestarts(low_level_ABS(y),
# establish a restart called 'negative_value'
# which returns the negative of it's argument
negative_value_restart=function(z){-z})
cat("Returning from mid_level_ABS()\n")
return(abs_y)
}
Наконец, высокоуровневый программист использует эту mid_level_ABS
функцию для вычисления абсолютного значения и устанавливает обработчик условия, который сообщает, что
mid_level_ABS
нужно восстанавливаться после negative_value
ошибки с помощью обработчика перезапуска.
high_level_ABS <- function(z){
abs_z <- withCallingHandlers(
# call this function
mid_level_ABS(z) ,
# and if an `error` occurres
error = function(err){
# and the `error` is a `negative_value` error
if(inherits(err,"negative_value")){
# invoke the restart called 'negative_value_restart'
invokeRestart('negative_value_restart',
# and invoke it with this parameter
err$x)
}else{
# otherwise re-raise the error
stop(err)
}
})
cat("Returning from high_level_ABS()\n")
return(abs_z)
}
Суть всего в том, что с помощью withRestarts()
и withCallingHandlers()
функция
high_level_ABS
смогла сообщить, mid_level_ABS
как восстанавливаться после ошибок, вызванных low_level_ABS
ошибкой, без остановки выполнения
mid_level_ABS
, с чем вы не можете сделать tryCatch()
:
> high_level_ABS(3)
Returning from low_level_ABS()
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
> high_level_ABS(-3)
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
На практике low_level_ABS
представляет функцию, которая mid_level_ABS
вызывает много (возможно, даже миллионы раз), для которой правильный метод обработки ошибок может варьироваться в зависимости от ситуации, а выбор того, как обрабатывать конкретные ошибки, предоставляется функциям более высокого уровня ( high_level_ABS
).
Функция перезапуска очень важна в R, унаследованном от Lisp. Это полезно, если вы хотите вызвать какую-либо функцию в теле цикла, и вы просто хотите, чтобы программа продолжалась, если вызов функции рухнет. Попробуйте этот код:
for (i in 1:20) withRestarts(tryCatch(
if((a <- runif(1))>0.5) print(a) else stop(a),
finally = print("loop body finished!")),
abort = function(){})