Ausnahmebehandlung in R [geschlossen]


97

Hat jemand Beispiele / Tutorials zur Ausnahmebehandlung in R? Die offizielle Dokumentation ist sehr knapp.


1
Dies ist auch ein gutes Beispiel: stackoverflow.com/q/12193779/2026975 .
Imriss

Ich fand diesen Blog-Beitrag sehr nützlich: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Antworten:


31

Neben der Antwort von Shane, die Sie auf andere StackOverflow-Diskussionen verweist, können Sie auch eine Codesuchfunktion ausprobieren. Diese ursprüngliche Antwort, die auf die Codesuche von Google verweist, wurde inzwischen eingestellt, aber Sie können es versuchen

Nur für die Aufzeichnung gibt es auch try, tryCatchkann aber vorzuziehen sein. Ich habe versucht, bei der Google-Codesuche schnell zu zählen, aber bei dem Versuch werden zu viele Fehlalarme für das Verb selbst angezeigt - es scheint tryCatchjedoch weit verbreitet zu sein.


Vielleicht könnte dieses Beispiel helfen: http://stackoverflow.com/a/12195574/2026975
imriss

Eine Github-Suche ist wahrscheinlich ein anständiger Ersatz für den nicht mehr existierenden Link.
Gregor Thomas

Alle Links sind defekt.
Toros91

60

Grundsätzlich möchten Sie die tryCatch()Funktion nutzen. Weitere Informationen finden Sie in der Hilfe ("tryCatch").

Hier ist ein triviales Beispiel (denken Sie daran, dass Sie mit einem Fehler tun können, was Sie wollen):

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

Schauen Sie sich diese verwandten Fragen an:



8

Die Funktion trycatch()ist ziemlich einfach und es gibt viele gute Tutorials dazu. Eine ausgezeichnete Erklärung für die Fehlerbehandlung in R findet sich in Hadley Wickhams Buch Advanced-R . Das Folgende ist eine sehr grundlegende Einführung in withCallingHandlers()und withRestarts()in so wenigen Worten wie möglich:

Nehmen wir an, ein Programmierer auf niedriger Ebene schreibt eine Funktion zur Berechnung des Absolutwerts. Er ist sich nicht sicher, wie er es berechnen soll, weiß aber, wie man einen Fehler konstruiert, und vermittelt fleißig seine Naivität:

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

Ein Programmierer mittlerer Ebene schreibt auch eine Funktion zur Berechnung des Absolutwerts, wobei er die leider unvollständige low_level_ABSFunktion verwendet. Er weiß, dass der Low-Level-Code einen negative_value Fehler auslöst, wenn der Wert von xnegativ ist, und schlägt eine Lösung für das Problem vor, indem er einen Wert festlegt restart, mit dem Benutzer mid_level_ABSsteuern können, wie mid_level_ABSein negative_valueFehler behoben wird (oder nicht) .

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

Schließlich verwendet ein übergeordneter Programmierer die mid_level_ABSFunktion, um den Absolutwert zu berechnen, und erstellt einen Bedingungshandler, der den Benutzer auffordert, mid_level_ABSeinen negative_valueFehler mithilfe des Neustarthandlers zu beheben.

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

Der Sinn all dessen ist, dass die Funktion mithilfe von withRestarts()und feststellen konnte, wie Fehler behoben werden können, die durch Fehler ausgelöst wurden, ohne die Ausführung von zu stoppen. Dies ist etwas, mit dem Sie nichts anfangen können :withCallingHandlers()high_level_ABSmid_level_ABSlow_level_ABSmid_level_ABStryCatch()

> 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

In der Praxis low_level_ABSstellt dies eine Funktion dar, mid_level_ABSdie häufig aufgerufen wird (möglicherweise sogar millionenfach), wobei die korrekte Methode zur Fehlerbehandlung je nach Situation variieren kann und die Wahl der Behandlung bestimmter Fehler den Funktionen höherer Ebenen überlassen bleibt ( high_level_ABS).


7

Die Neustartfunktion ist in R, das von Lisp geerbt wurde, sehr wichtig. Dies ist nützlich, wenn Sie eine Funktion im Schleifenkörper aufrufen möchten und das Programm nur fortgesetzt werden soll, wenn der Funktionsaufruf zusammenbricht. Versuchen Sie diesen 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(){})
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.