Gestione delle eccezioni in R [chiuso]


97

Qualcuno ha esempi / tutorial sulla gestione delle eccezioni in R? La documentazione ufficiale è molto concisa.


1
Anche questo è un buon esempio: stackoverflow.com/q/12193779/2026975 .
imriss

Ho trovato questo post del blog abbastanza utile: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Risposte:


31

Oltre alla risposta di Shane che ti punta ad altre discussioni StackOverflow, potresti provare una funzione di ricerca del codice. Questa risposta originale indicava la ricerca del codice di Google da allora è stata interrotta, ma puoi provare

Solo per la cronaca, c'è anche tryma tryCatchpotrebbe essere preferibile. Ho provato un conteggio veloce in Google Code Search, ma try ottiene troppi falsi positivi per il verbo stesso, ma sembra che tryCatchsia più ampiamente utilizzato.


Forse questo esempio potrebbe aiutare: http://stackoverflow.com/a/12195574/2026975
imriss

Una ricerca su GitHub è probabilmente un sostituto decente per il collegamento defunto.
Gregor Thomas

Tutti i collegamenti sono interrotti.
Toros91

60

Fondamentalmente vuoi usare la tryCatch()funzione. Guarda help ("tryCatch") per maggiori dettagli.

Ecco un esempio banale (tieni presente che puoi fare quello che vuoi con un errore):

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

Dai un'occhiata a queste domande correlate:



8

La funzione trycatch()è abbastanza semplice e ci sono molti buoni tutorial su questo. Un'eccellente spiegazione della gestione degli errori in R può essere trovata nel libro Advanced-R di Hadley Wickham , e ciò che segue è un'introduzione molto semplice withCallingHandlers()e withRestarts()con il minor numero di parole possibile:

Diciamo che un programmatore di basso livello scrive una funzione per calcolare il valore assoluto. Non sa bene come calcolarlo, ma sa come costruire un errore e trasmette diligentemente la sua ingenuità:

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 programmatore di medio livello scrive anche una funzione per calcolare il valore assoluto, facendo uso della low_level_ABSfunzione tristemente incompleta . Sa che il codice di basso livello genera un negative_value errore quando il valore di xè negativo e suggerisce una soluzione al problema, stabilendo una restartche consente agli utenti di mid_level_ABSdi controllare il modo in cui si mid_level_ABSrisolve (o non si) da un negative_valueerrore.

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

Infine, un programmatore di alto livello utilizza la mid_level_ABSfunzione per calcolare il valore assoluto e stabilisce un gestore di condizioni che dice al gestore mid_level_ABSdi recuperare da un negative_valueerrore utilizzando il gestore di riavvio.

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

Il punto di tutto questo è che utilizzando withRestarts()e withCallingHandlers(), la funzione è high_level_ABSstata in grado di dire mid_level_ABScome recuperare da errori generati da low_level_ABSerrore senza interrompere l'esecuzione di mid_level_ABS, cosa che non puoi fare con 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

In pratica, low_level_ABSrappresenta una funzione che mid_level_ABSchiama molte (forse anche milioni di volte), per la quale il metodo corretto di gestione degli errori può variare a seconda della situazione, e la scelta di come gestire errori specifici è lasciata alle funzioni di livello superiore ( high_level_ABS).


7

La funzione di riavvio è molto importante in R ereditato da Lisp. È utile se si desidera chiamare una funzione nel corpo del ciclo e si desidera solo che il programma continui se la chiamata alla funzione si interrompe. Prova questo codice:

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(){})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.