2010-04-12 20 views
94

Czy ktoś ma przykłady/samouczki obsługi wyjątków w R? Oficjalna dokumentacja jest bardzo lakoniczna.Obsługa wyjątków w R

+1

Ten jest również dobrym przykładem: http://stackoverflow.com/q/12193779/2026975. – imriss

+0

Znalazłem ten wpis na blogu, aby był całkiem przydatny: [http://mazamascience.com/WorkingWithData/?p=912](http://mazamascience.com/WorkingWithData/?p=912) –

+0

Poprosiłem o temat dokumentacji SO na to pytanie. – Leonid

Odpowiedz

30

Poza odpowiedzią Shane'a na inne dyskusje StackOverflow, możesz wypróbować funkcję wyszukiwania kodu. Ta oryginalna odpowiedź wskazał na Google Code Search został już wycofany, ale można spróbować

Tak dla przypomnienia, istnieje również try ale tryCatch może być korzystne. Próbowałem szybko policzyć w Wyszukiwarce kodów Google, ale próbuję uzyskać zbyt wiele fałszywych trafień dla samego czasownika - jednak wydaje się, że jest on powszechnie używany.

+0

Może ten przykład może pomóc: [http://stackoverflow.com/a/12195574/2026975](http://stackoverflow.com/a/12195574/2026975) – imriss

+0

A [Wyszukiwanie Github] (https: // github. com/search? q = tryCatch + language% 3AR & type = Code & ref = searchresults) to prawdopodobnie przyzwoity zamiennik dla nieistniejącego łącza. – Gregor

58

Zasadniczo chcesz użyć funkcji tryCatch(). Sprawdź pomoc ("tryCatch"), aby uzyskać więcej informacji.

Oto trywialny przykład (pamiętaj, że możesz robić, co chcesz z błędem):

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

Wystarczy popatrzeć na tych pokrewnych pytania:

+1

Trzecie łącze nie jest łączem. – Marek

+8

Wina Not Shane'a - prawdopodobnie błąd w wyliczeniu regularnym określający sposób oznaczania treści na SO. –

7

Funkcja restartu jest bardzo ważna w dziedziczeniu R z Lisp. Jest to przydatne, jeśli chcesz wywołać jakąś funkcję w ciele pętli i chcesz, aby program był kontynuowany, jeśli wywołanie funkcji zostanie zwinięte. Spróbuj ten kod:

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(){}) 
6

Funkcja trycatch() jest dość proste, i istnieje wiele dobrych tutoriali na ten temat. Doskonały wyjaśnienie obsługi w R błędu można znaleźć w książce Hadley Wickhama Advanced-R, a co za tym idzie jest bardzo podstawowy intro withCallingHandlers() i withRestarts() w jak najmniejszej liczbie słów, jak to możliwe:

Powiedzmy programistą niski poziom pisze funkcja do obliczenia bezwzględnej wartości . On nie jest pewien, jak go obliczyć, ale wie how to construct an error i pilnie przekazuje swoją naiwność:

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

Mid-level programista pisze także funkcję do obliczania wartości bezwzględnej, dzięki czemu korzystanie z funkcji żałośnie niepełnej low_level_ABS .On wie, że kod niski poziom rzuca negative_value błąd, gdy wartość x jest ujemny i sugeruje rozwiązanie problemu przez ustanowienia restart która pozwala użytkownikom mid_level_ABS kontrolować drogę w którym mid_level_ABS odzyskuje (lub nie) z powodu błędu negative_value.

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

Wreszcie, programista wysoki poziom wykorzystuje funkcję mid_level_ABS obliczyć wartość bezwzględną, oraz ustanawia procedury obsługi warunek, który opowiada mid_level_ABS odzyskać od błędu negative_value za pomocą restartu obsługi.

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

Chodzi w tym wszystkim jest to, że za pomocą withRestarts() i withCallingHandlers(), funkcję high_level_ABS był w stanie powiedzieć mid_level_ABS jak odzyskać od błędów podniesiony przez low_level_ABS błędu bez zatrzymywania wykonanie mid_level_ABS, która jest czymś nie można zrobić z 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 

W praktyce low_level_ABS oznacza funkcję, która mid_level_ABS wywołuje dużo (być może nawet miliony razy), dla których właściwa metoda błąd postępowania może zależeć od sytuacji, a wybór sposobu obsługi konkretnych błędów jest lewej do wyższych funkcji poziomu (high_level_ABS).