Xử lý ngoại lệ trong R [đóng]


97

Có ai có ví dụ / hướng dẫn xử lý ngoại lệ trong R không? Các tài liệu chính thức là rất ngắn gọn.


1
Đây cũng là một ví dụ điển hình: stackoverflow.com/q/12193779/2026975 .
imriss

Tôi thấy bài đăng trên blog này khá hữu ích: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

Câu trả lời:


31

Bên cạnh câu trả lời của Shane hướng dẫn bạn đến các cuộc thảo luận StackOverflow khác, bạn có thể thử tính năng tìm kiếm mã. Câu trả lời ban đầu này chỉ đến Tìm kiếm mã của Google đã ngừng hoạt động, nhưng bạn có thể thử

Chỉ đối với hồ sơ, cũng có trynhưng tryCatchcó thể tốt hơn. Tôi đã thử đếm nhanh tại Google Code Search nhưng thử thì nhận được quá nhiều dương tính sai cho chính động từ - nhưng nó có vẻ tryCatchđược sử dụng rộng rãi hơn.


Có lẽ ví dụ này có thể giúp: http://stackoverflow.com/a/12195574/2026975
imriss

Một Github tìm kiếm có lẽ là một sự thay thế khá cho các liên kết không còn tồn tại.
Gregor Thomas

Tất cả các liên kết bị hỏng.
Toros91

60

Về cơ bản bạn muốn sử dụng tryCatch()chức năng. Xem phần trợ giúp ("tryCatch") để biết thêm chi tiết.

Đây là một ví dụ nhỏ (hãy nhớ rằng bạn có thể làm bất cứ điều gì bạn muốn với một lỗi):

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

Hãy xem những câu hỏi liên quan sau:



8

Chức năng trycatch()này khá đơn giản và có rất nhiều hướng dẫn tốt về điều đó. Bạn có thể tìm thấy lời giải thích tuyệt vời về cách xử lý lỗi trong R trong cuốn sách Advanced-R của Hadley Wickham và những gì sau đây là phần giới thiệu rất cơ bản về withCallingHandlers()withRestarts()càng ít từ càng tốt:

Giả sử một lập trình viên cấp thấp viết một hàm để tính giá trị tuyệt đối. Anh ấy không chắc cách tính toán nó, nhưng biết cách tính lỗi và siêng năng truyền đạt câu nói ngây thơ của mình:

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

Một lập trình viên trung cấp cũng viết một hàm để tính giá trị tuyệt đối, sử dụng low_level_ABShàm không đầy đủ một cách đáng tiếc . Anh ta biết rằng mã cấp thấp tạo ra negative_value lỗi khi giá trị của xlà âm và đề xuất giải pháp cho vấn đề, bằng cách thiết lập một mã restartcho phép người dùng mid_level_ABSkiểm soát cách mid_level_ABSkhôi phục (hoặc không) từ negative_valuelỗi.

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

Cuối cùng, một lập trình viên cấp cao sử dụng mid_level_ABShàm để tính toán giá trị tuyệt đối và thiết lập một trình xử lý điều kiện để yêu cầu mid_level_ABSkhôi phục negative_valuelỗi bằng cách sử dụng trình xử lý khởi động lại.

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

Điểm mấu chốt của tất cả điều này là bằng cách sử dụng withRestarts()withCallingHandlers(), hàm high_level_ABScó thể cho biết mid_level_ABScách khôi phục các lỗi do low_level_ABSlỗi gây ra mà không ngừng thực hiện mid_level_ABS, đây là điều bạn không thể làm với 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

Trong thực tế, low_level_ABSđại diện cho một hàm mid_level_ABSgọi rất nhiều (thậm chí có thể hàng triệu lần), trong đó phương pháp xử lý lỗi chính xác có thể khác nhau tùy theo tình huống và việc lựa chọn cách xử lý các lỗi cụ thể được để cho các hàm cấp cao hơn ( high_level_ABS).


7

Chức năng khởi động lại rất quan trọng trong R được kế thừa từ Lisp. Sẽ rất hữu ích nếu bạn muốn gọi một số hàm trong thân vòng lặp và bạn chỉ muốn chương trình tiếp tục nếu lệnh gọi hàm bị sập. Hãy thử mã này:

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(){})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.