98 votes

Gestion des exceptions en R

Est-ce que quelqu'un a des exemples/tutoriels de gestion des exceptions en R? La documentation officielle est très succincte.

60voto

Shane Points 40885

Essentiellement, vous voulez utiliser la fonction tryCatch(). 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("réussit"), error = function(e) print(vari), finally=print("terminé")) 
tryCatch(stop("échoue"), error = function(e) print(vari), finally=print("terminé")) 

Jetez un œil à ces questions connexes :

31voto

Dirk Eddelbuettel Points 134700

Outre la réponse de Shane qui vous redirige vers d'autres discussions StackOverflow, vous pourriez essayer une fonction de recherche de code. Cette réponse originale renvoyait vers la fonction de recherche de code de Google, qui a depuis été abandonnée, mais vous pouvez essayer

Juste pour information, il y a également la fonction try mais tryCatch peut être préférable. J'ai fait un rapide compte sur Google Code Search mais try donne trop de faux positifs pour le verbe lui-même -- il semble toutefois que tryCatch soit plus largement utilisé.

22voto

isomorphismes Points 1902

Ce résultat d'une recherche Google connexe m'a aidé : http://biocodenv.com/wordpress/?p=15.

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

10voto

Jthorpe Points 6559

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

Imaginons qu'un programmeur de bas niveau écrive une fonction pour calculer la valeur absolue. Il n'est pas sûr de comment le calculer, mais sait comment construire une erreur et indique sincèrement sa naïveté :

low_level_ABS <- function(x){
    if(x<0){
        #construire une erreur
        negative_value_error <- structure(
                    # avec la classe `negative_value`
                    class = c("negative_value","error", "condition"),
                    list(message = "Pas sûr de quoi faire avec une valeur négative",
                         call = sys.call(), 
                         # et inclure le paramètre fautif dans l'objet d'erreur
                         x=x))
        # lever l'erreur
        stop(negative_value_error)
    }
    cat("Retour de low_level_ABS()\n")
    return(x)
}

Un programmeur de niveau intermédiaire écrit également une fonction pour calculer la valeur absolue, en utilisant la fonction low_level_ABS incroyablement incomplète. Il sait que le code de bas niveau génère une erreur negative_value lorsque la valeur de x est négative et suggère une solution au problème, en établissant un restart qui permet aux utilisateurs de mid_level_ABS de contrôler la manière dont mid_level_ABS récupère (ou non) d'une erreur de type negative_value.

mid_level_ABS <- function(y){
    abs_y <- withRestarts(low_level_ABS(y), 
                          # établir un restart appelé 'negative_value'
                          # qui renvoie le négatif de son argument
                          negative_value_restart=function(z){-z}) 
    cat("Retour de mid_level_ABS()\n")
    return(abs_y)
}

Enfin, un programmeur de haut niveau utilise la fonction mid_level_ABS pour calculer la valeur absolue, et établit un gestionnaire de conditions qui indique à mid_level_ABS de récupérer d'une erreur de type negative_value en utilisant le gestionnaire de restart.

high_level_ABS <- function(z){
    abs_z <- withCallingHandlers(
            # appeler cette fonction
            mid_level_ABS(z) ,
            # et si une `error` se produit
            error = function(err){
                # et que l'`error` est une erreur de type `negative_value`
                if(inherits(err,"negative_value")){
                    # invoquer le restart appelé 'negative_value_restart'
                    invokeRestart('negative_value_restart', 
                                     # et l'invoquer avec ce paramètre
                                     err$x) 
                }else{
                    # sinon, relancer l'erreur
                    stop(err)
                }
            })
    cat("Retour de high_level_ABS()\n")
    return(abs_z)
}

Le but de tout cela est qu'en utilisant withRestarts() et withCallingHandlers(), la fonction high_level_ABS a pu dire à mid_level_ABS comment récupérer les erreurs générées par low_level_ABS sans arrêter l'exécution de mid_level_ABS, ce que l'on ne peut pas faire avec tryCatch() :

> high_level_ABS(3)
Retour de low_level_ABS()
Retour de mid_level_ABS()
Retour de high_level_ABS()
[1] 3
> high_level_ABS(-3)
Retour de mid_level_ABS()
Retour de high_level_ABS()
[1] 3

En pratique, low_level_ABS représente une fonction que mid_level_ABS appelle fréquemment (peut-être même des millions de fois), pour laquelle la méthode correcte de gestion des erreurs peut varier en fonction de la situation, et le choix de la manière de traiter des erreurs spécifiques est laissé aux fonctions de niveau supérieur (high_level_ABS).

7voto

Xin Guo Points 515

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

for (i in 1:20) withRestarts(tryCatch(
if((a <- runif(1))>0.5) print(a) else stop(a),
finally = print("fin du corps de la boucle!")), 
abort = function(){})

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X