Penanganan pengecualian di R [tertutup]

97

Apakah ada yang punya contoh / tutorial penanganan pengecualian di R? Dokumentasi resminya sangat singkat.

gappy
sumber
1
Yang ini juga contoh yang bagus: stackoverflow.com/q/12193779/2026975 .
imriss
Saya menemukan entri blog ini cukup berguna: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Jawaban:

31

Selain jawaban Shane yang mengarahkan Anda ke diskusi StackOverflow lainnya, Anda dapat mencoba fitur pencarian kode. Jawaban asli yang menunjuk ke Pencarian Kode Google ini telah dihentikan, tetapi Anda dapat mencoba

Sekadar catatan, ada juga trytapi tryCatchmungkin lebih disukai. Saya mencoba hitung cepat di Google Code Search tetapi mencoba mendapatkan terlalu banyak positif palsu untuk kata kerja itu sendiri - namun tampaknya tryCatchini lebih banyak digunakan.

Dirk Eddelbuettel
sumber
Mungkin contoh ini dapat membantu: http://stackoverflow.com/a/12195574/2026975
imriss
Sebuah Github pencarian mungkin pengganti yang layak untuk link mati.
Gregor Thomas
Semua tautan rusak.
Toros91
60

Pada dasarnya Anda ingin menggunakan tryCatch()fungsi tersebut. Lihat bantuan ("tryCatch") untuk lebih jelasnya.

Berikut adalah contoh sepele (perlu diingat bahwa Anda dapat melakukan apa pun yang Anda inginkan dengan kesalahan):

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

Lihat pertanyaan terkait ini:

Shane
sumber
22

Hasil dari pencarian google terkait ini membantu saya: http://biocodenv.com/wordpress/?p=15 .

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

Fungsinya trycatch()cukup mudah, dan ada banyak tutorial bagus tentang itu. Penjelasan yang sangat baik tentang penanganan kesalahan di R dapat ditemukan dalam buku Hadley Wickham Advanced-R , dan berikut ini adalah pengantar yang sangat mendasar withCallingHandlers()dan withRestarts()dalam kata-kata sesedikit mungkin:

Katakanlah seorang programmer tingkat rendah menulis sebuah fungsi untuk menghitung nilai absolut. Dia tidak yakin bagaimana cara menghitungnya, tapi tahu bagaimana membuat kesalahan dan dengan rajin menyampaikan kenaifannya:

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

Seorang programmer tingkat menengah juga menulis sebuah fungsi untuk menghitung nilai absolut, memanfaatkan low_level_ABSfungsi yang sayangnya tidak lengkap tersebut . Dia tahu bahwa kode tingkat rendah melempar negative_value kesalahan ketika nilai xnegatif dan menyarankan solusi untuk masalah, dengan menetapkan restartyang memungkinkan pengguna mid_level_ABSuntuk mengontrol cara di mana mid_level_ABSpulih (atau tidak) dari negative_valuekesalahan.

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

Akhirnya, pemrogram tingkat tinggi menggunakan mid_level_ABSfungsi tersebut untuk menghitung nilai absolut, dan menetapkan penangan kondisi yang memberi tahu mid_level_ABSuntuk memulihkan dari negative_valuekesalahan dengan menggunakan penangan restart.

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

Inti dari semua ini adalah bahwa dengan menggunakan withRestarts()dan withCallingHandlers(), fungsi high_level_ABStersebut dapat mengetahui mid_level_ABScara memulihkan dari kesalahan yang disebabkan oleh low_level_ABSkesalahan tanpa menghentikan eksekusi mid_level_ABS, yang merupakan sesuatu yang tidak dapat Anda lakukan dengan 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

Dalam praktiknya, low_level_ABSmerepresentasikan fungsi yang mid_level_ABSmemanggil banyak (bahkan mungkin jutaan kali), di mana metode penanganan error yang benar dapat bervariasi menurut situasi, dan pilihan cara menangani error tertentu diserahkan ke fungsi tingkat yang lebih tinggi ( high_level_ABS).

Jthorpe
sumber
7

Fungsi restart sangat penting di R yang diwarisi dari Lisp. Ini berguna jika Anda ingin memanggil beberapa fungsi di badan perulangan dan Anda hanya ingin program melanjutkan jika pemanggilan fungsi runtuh. Coba kode ini:

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
sumber