Обработка исключений в R [закрыто]

97

Есть ли у кого-нибудь примеры / руководства по обработке исключений в R? Официальная документация очень краткая.

непослушный
источник
1
Это тоже хороший пример: stackoverflow.com/q/12193779/2026975 .
imriss
Я нашел этот пост в блоге весьма полезным: http://mazamascience.com/WorkingWithData/?p=912
paul_dg 02

Ответы:

31

Помимо ответа Шейна, указывающего на другие обсуждения StackOverflow, вы можете попробовать функцию поиска кода. Этот исходный ответ указывал на поиск кода Google, который с тех пор был прекращен, но вы можете попробовать

Просто для записи, есть также, tryно tryCatchможет быть предпочтительнее. Я попробовал быстро подсчитать в Google Code Search, но попытка дает слишком много ложных срабатываний для самого глагола - но, похоже, tryCatchон более широко используется.

Дирк Эддельбюттель
источник
Может быть, этот пример может помочь: http://stackoverflow.com/a/12195574/2026975
imriss
Поиск Github , вероятно , является достойной заменой для несуществующей ссылки.
Грегор Томас
Все ссылки битые.
Toros91
60

В основном вы хотите использовать 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")) 

Взгляните на эти связанные вопросы:

Шейн
источник
8

Функция 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).

Jthorpe
источник
7

Функция перезапуска очень важна в 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(){})
Синь Го
источник