Est-ce que quelqu'un a des exemples/tutoriels de gestion des exceptions en R? La documentation officielle est très succincte.
Réponses
Trop de publicités?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 :
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
- la recherche sur Github comme par exemple dans cette requête pour tryCatch en langage R;
- la recherche de code Ohloh/Blackduck par exemple cette requête pour tryCatch dans les fichiers R
- le moteur de recherche de code Debian sur l'ensemble de l'archive Debian
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é.
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;
}
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
).
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(){})