Tratamento de exceções em R [fechado]

97

Alguém tem exemplos / tutoriais de tratamento de exceções em R? A documentação oficial é muito concisa.

boquiaberto
fonte
1
Este também é um bom exemplo: stackoverflow.com/q/12193779/2026975 .
imriss de
Achei esta postagem do blog bastante útil: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Respostas:

31

Além da resposta de Shane apontando para outras discussões StackOverflow, você pode tentar um recurso de pesquisa de código. Esta resposta original apontava para a Pesquisa de código do Google que foi descontinuada, mas você pode tentar

Apenas para registro, existe também, trymas tryCatchpode ser preferível. Eu tentei uma contagem rápida no Google Code Search, mas tentei obter muitos falsos positivos para o próprio verbo - mas parece que tryCatché mais amplamente usado.

Dirk Eddelbuettel
fonte
Talvez este exemplo possa ajudar: http://stackoverflow.com/a/12195574/2026975
imriss
Uma pesquisa no Github é provavelmente um substituto decente para o link extinto.
Gregor Thomas
Todos os links estão quebrados.
Toros91
60

Basicamente, você deseja usar a tryCatch()função. Veja a ajuda ("tryCatch") para mais detalhes.

Aqui está um exemplo trivial (tenha em mente que você pode fazer o que quiser com um erro):

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

Dê uma olhada nessas questões relacionadas:

Shane
fonte
22

Este resultado de uma pesquisa do Google relacionada me ajudou: http://biocodenv.com/wordpress/?p=15 .

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

A função trycatch()é bastante simples e existem muitos bons tutoriais sobre isso. Uma excelente explicação do tratamento de erros em R pode ser encontrada no livro Advanced-R de Hadley Wickham , e o que se segue é uma introdução muito básica withCallingHandlers()e withRestarts()com o mínimo de palavras possível:

Digamos que um programador de baixo nível escreva uma função para calcular o valor absoluto. Ele não tem certeza de como calculá-lo, mas sabe como construir um erro e transmite diligentemente sua ingenuidade:

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

Um programador de nível médio também escreve uma função para calcular o valor absoluto, fazendo uso da low_level_ABSfunção lamentavelmente incompleta . Ele sabe que o código de baixo nível gera um negative_value erro quando o valor de xé negativo e sugere uma solução para o problema, estabelecendo umrestart que permite aos usuários de mid_level_ABScontrolar a forma como se mid_level_ABSrecupera (ou não) de um negative_valueerro.

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

Finalmente, um programador de alto nível usa o mid_level_ABS função para calcular o valor absoluto e estabelece um manipulador de condição que diz ao mid_level_ABSpara se recuperar de um negative_valueerro usando o manipulador de reinicialização.

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

O ponto de tudo isso é que usando withRestarts()e withCallingHandlers(), a função high_level_ABSfoi capaz de dizer mid_level_ABScomo se recuperar de erros levantados porlow_level_ABS erro sem interromper a execução de mid_level_ABS, que é algo que você não pode fazer com 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

Na prática, low_level_ABSrepresenta uma função que mid_level_ABSchama muito (talvez até milhões de vezes), para a qual o método correto de tratamento de erros pode variar de acordo com a situação, e a escolha de como tratar erros específicos é deixada para funções de nível superior ( high_level_ABS).

Jthorpe
fonte
7

A função de reinicialização é muito importante no R herdado do Lisp. É útil se você deseja chamar alguma função no corpo do loop e deseja apenas que o programa continue se a chamada da função for interrompida. Experimente 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
fonte