Manejo de excepciones en R [cerrado]

97

¿Alguien tiene ejemplos / tutoriales de manejo de excepciones en R? La documentación oficial es muy concisa.

boquiabierto
fuente
1
Este también es un buen ejemplo: stackoverflow.com/q/12193779/2026975 .
imriss
Encontré esta publicación de blog bastante útil: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Respuestas:

31

Además de la respuesta de Shane que le indica otras discusiones de StackOverflow, puede probar una función de búsqueda de código. Esta respuesta original apuntaba a la búsqueda de código de Google desde entonces ha sido descontinuada, pero puede intentar

Solo para que conste, también existe, trypero tryCatchpuede ser preferible. Probé un conteo rápido en Google Code Search, pero el intento obtiene demasiados falsos positivos para el verbo en sí, pero parece que tryCatchse usa más ampliamente.

Dirk Eddelbuettel
fuente
Quizás este ejemplo podría ayudar: http://stackoverflow.com/a/12195574/2026975
imriss
Una búsqueda en Github es probablemente un reemplazo decente para el enlace desaparecido.
Gregor Thomas
Todos los enlaces están rotos.
Toros91
60

Básicamente quieres usar la tryCatch()función. Consulte la ayuda ("tryCatch") para obtener más detalles.

Aquí hay un ejemplo trivial (tenga en cuenta que puede hacer lo que quiera con un error):

vari <- 1
tryCatch(print("passes"), error = function(e) print(vari), finally=print("finished")) 
tryCatch(stop("fails"), error = function(e) print(vari), finally=print("finished")) 

Eche un vistazo a estas preguntas relacionadas:

Shane
fuente
22

Este resultado de una búsqueda relacionada en Google me ayudó: http://biocodenv.com/wordpress/?p=15 .

for(i in 1:16){
result <- try(nonlinear_modeling(i));
if(class(result) == "try-error") next;
}
isomorfismos
fuente
8

La función trycatch()es bastante sencilla y hay muchos buenos tutoriales sobre eso. Se puede encontrar una excelente explicación del manejo de errores en R en el libro Advanced-R de Hadley Wickham , y lo que sigue es una introducción muy básica withCallingHandlers()y withRestarts()en la menor cantidad de palabras posible:

Digamos que un programador de bajo nivel escribe una función para calcular el valor absoluto. No está seguro de cómo calcularlo, pero sabe cómo construir un error y transmite diligentemente su ingenuidad:

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)
}

Un programador de nivel medio también escribe una función para calcular el valor absoluto, haciendo uso de la low_level_ABSfunción lamentablemente incompleta . Sabe que el código de bajo nivel arroja un negative_value error cuando el valor de xes negativo y sugiere una solución al problema, al establecer un código restartque permite a los usuarios de mid_level_ABScontrolar la forma en que se mid_level_ABSrecupera (o no) de un negative_valueerror.

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)
}

Por último, un programador de alto nivel usa la mid_level_ABSfunción para calcular el valor absoluto y establece un controlador de condición que le dice al mid_level_ABSque se recupere de un negative_valueerror usando el controlador de reinicio.

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)
}

El punto de todo esto es que al usar withRestarts()y withCallingHandlers(), la función high_level_ABSfue capaz de decir mid_level_ABScómo recuperarse de los errores generados por low_level_ABSerror sin detener la ejecución de mid_level_ABS, que es algo que no se puede hacer con 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

En la práctica, low_level_ABSrepresenta una función que mid_level_ABSllama mucho (quizás incluso millones de veces), por lo que el método correcto de manejo de errores puede variar según la situación, y la elección de cómo manejar errores específicos se deja a funciones de nivel superior ( high_level_ABS).

Jthorpe
fuente
7

La función de reinicio es muy importante en R heredado de Lisp. Es útil si desea llamar a alguna función en el cuerpo del bucle y solo desea que el programa continúe si la llamada a la función colapsa. Prueba este código:

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(){})
Xin Guo
fuente