Traitement des exceptions dans R [fermé]

97

Quelqu'un a-t-il des exemples / tutoriels de gestion des exceptions dans R? La documentation officielle est très concise.

gappy
la source
1
Celui-ci est également un bon exemple: stackoverflow.com/q/12193779/2026975 .
imriss
J'ai trouvé ce billet de blog très utile: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Réponses:

31

Outre la réponse de Shane qui vous renvoie vers d'autres discussions StackOverflow, vous pouvez essayer une fonction de recherche de code. Cette réponse originale indiquait que la recherche de code de Google a depuis été interrompue, mais vous pouvez essayer

Pour mémoire, il y en a aussi, trymais cela tryCatchpeut être préférable. J'ai essayé un compte rapide sur Google Code Search, mais essayez d'obtenir trop de faux positifs pour le verbe lui-même - mais il semble qu'il tryCatchsoit plus largement utilisé.

Dirk Eddelbuettel
la source
Peut-être que cet exemple pourrait vous aider: http://stackoverflow.com/a/12195574/2026975
imriss
Une recherche Github est probablement un remplacement décent pour le lien obsolète.
Gregor Thomas
Tous les liens sont rompus.
Toros91
60

En gros, vous souhaitez utiliser la tryCatch()fonction. Consultez l'aide ("tryCatch") pour plus de détails.

Voici un exemple trivial (gardez à l'esprit que vous pouvez faire ce que vous voulez avec une erreur):

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

Jetez un œil à ces questions connexes:

Shane
la source
8

La fonction trycatch()est assez simple et il existe de nombreux bons tutoriels à ce sujet. Une excellente explication de la gestion des erreurs dans R peut être trouvée dans le livre Advanced-R de Hadley Wickham , et ce qui suit est une introduction très basique withCallingHandlers()et withRestarts()en aussi peu de mots que possible:

Disons qu'un programmeur de bas niveau écrit une fonction pour calculer la valeur absolue. Il ne sait pas comment la calculer, mais sait construire une erreur et exprime avec diligence sa naïveté:

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 programmeur de niveau intermédiaire écrit également une fonction pour calculer la valeur absolue, en utilisant la low_level_ABSfonction terriblement incomplète . Il sait que le code de bas niveau génère une negative_value erreur lorsque la valeur de xest négative et suggère une solution au problème, en établissant un restartqui permet aux utilisateurs de mid_level_ABScontrôler la manière dont se mid_level_ABSremet (ou non) une negative_valueerreur.

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

Enfin, un programmeur de haut niveau utilise la mid_level_ABSfonction pour calculer la valeur absolue et établit un gestionnaire de conditions qui indique au mid_level_ABSde récupérer d'une negative_valueerreur à l'aide du gestionnaire de redémarrage.

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

Le but de tout cela est qu'en utilisant withRestarts()et withCallingHandlers(), la fonction high_level_ABSa pu indiquer mid_level_ABScomment récupérer des erreurs générées par une low_level_ABSerreur sans arrêter l'exécution de mid_level_ABS, ce que vous ne pouvez pas faire avec 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 pratique, low_level_ABSreprésente une fonction qui mid_level_ABSappelle beaucoup (peut-être même des millions de fois), pour laquelle la méthode correcte de gestion des erreurs peut varier selon la situation, et le choix de la façon de gérer des erreurs spécifiques est laissé aux fonctions de niveau supérieur ( high_level_ABS).

Jthorpe
la source
7

La fonction de redémarrage est très importante dans R hérité de Lisp. C'est utile si vous voulez appeler une fonction dans le corps de la boucle et que vous voulez simplement que le programme continue si l'appel de fonction s'effondre. Essayez ce code:

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
la source