การจัดการข้อยกเว้นใน R [ปิด]


97

ใครมีตัวอย่าง / บทช่วยสอนเกี่ยวกับการจัดการข้อยกเว้นใน R? เอกสารอย่างเป็นทางการค่อนข้างสั้นมาก


1
หนึ่งนี้ยังเป็นตัวอย่างที่ดี: stackoverflow.com/q/12193779/2026975
imriss

ฉันพบว่าบล็อกโพสต์นี้มีประโยชน์มาก: http://mazamascience.com/WorkingWithData/?p=912
paul_dg

คำตอบ:


31

นอกจากคำตอบของ Shane ที่ชี้ให้คุณเห็นการสนทนา StackOverflow อื่น ๆ แล้วคุณสามารถลองใช้คุณลักษณะการค้นหารหัส คำตอบเดิมนี้ชี้ไปที่ Code Search ของ Google ได้ถูกยกเลิกไปแล้ว แต่คุณสามารถลองได้

สำหรับบันทึกก็มีเช่นกันtryแต่tryCatchอาจดีกว่า ฉันลองนับอย่างรวดเร็วที่ Google Code Search แต่ลองรับผลบวกเท็จมากเกินไปสำหรับคำกริยานั้นเอง แต่ดูเหมือนว่าtryCatchจะใช้กันอย่างแพร่หลาย


ตัวอย่างนี้อาจช่วยได้: http://stackoverflow.com/a/12195574/2026975
imriss

การค้นหา Githubน่าจะเป็นสิ่งทดแทนที่ดีสำหรับลิงก์ที่เสียไป
Gregor Thomas

ลิงค์ทั้งหมดเสีย
Toros91

60

โดยทั่วไปคุณต้องการใช้tryCatch()ฟังก์ชัน ดูวิธีใช้ ("tryCatch") สำหรับรายละเอียดเพิ่มเติม

นี่คือตัวอย่างเล็กน้อย (โปรดทราบว่าคุณสามารถทำอะไรก็ได้ที่ต้องการโดยมีข้อผิดพลาด):

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

ดูคำถามที่เกี่ยวข้องเหล่านี้:


22

ผลที่ได้นี้มาจากการค้นหาของ Google ที่เกี่ยวข้องช่วยให้ฉัน: http://biocodenv.com/wordpress/?p=15

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

8

ฟังก์ชั่นtrycatch()นี้ค่อนข้างตรงไปตรงมาและมีบทเรียนที่ดีมากมายเกี่ยวกับเรื่องนี้ คำอธิบายที่ดีเยี่ยมในการจัดการข้อผิดพลาดในการวิจัยสามารถพบได้ใน Hadley Wickham หนังสือขั้นสูง-Rและสิ่งที่ตามมาคือมากบทนำพื้นฐานในการwithCallingHandlers()และwithRestarts()ในขณะที่คำไม่กี่คำที่เป็นไปได้:

สมมติว่าโปรแกรมเมอร์ระดับต่ำเขียนฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์ เขาไม่แน่ใจว่าจะคำนวณอย่างไร แต่รู้วิธีสร้างข้อผิดพลาดและสื่อถึงความไร้เดียงสาของเขาอย่างขยันขันแข็ง:

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

โปรแกรมเมอร์ระดับกลางยังเขียนฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์โดยใช้low_level_ABSฟังก์ชันที่ไม่สมบูรณ์อย่างวิบัติ เขารู้ว่ารหัสระดับต่ำจะแสดงnegative_value ข้อผิดพลาดเมื่อค่าxเป็นลบและแนะนำวิธีแก้ปัญหาโดยการสร้างรหัสrestartที่ช่วยให้ผู้ใช้mid_level_ABSสามารถควบคุมวิธีการmid_level_ABSกู้คืน (หรือไม่) จาก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)
}

สุดท้ายโปรแกรมเมอร์ระดับสูงจะใช้mid_level_ABSฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์และสร้างตัวจัดการเงื่อนไขซึ่งบอก mid_level_ABSให้กู้คืนจากnegative_valueข้อผิดพลาดโดยใช้ตัวจัดการรีสตาร์ท

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

จุดทั้งหมดนี้คือว่าด้วยการใช้withRestarts()และwithCallingHandlers()ฟังก์ชั่น high_level_ABSก็สามารถที่จะบอกmid_level_ABSวิธีการกู้คืนจากข้อผิดพลาดที่เกิดขึ้นโดยlow_level_ABSข้อผิดพลาดโดยไม่ต้องหยุดการดำเนินการ mid_level_ABSซึ่งเป็นสิ่งที่คุณไม่สามารถทำอะไรกับ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

ในทางปฏิบัติlow_level_ABSหมายถึงฟังก์ชันที่mid_level_ABSเรียกใช้จำนวนมาก (อาจถึงล้านครั้ง) ซึ่งวิธีการจัดการข้อผิดพลาดที่ถูกต้องอาจแตกต่างกันไปตามสถานการณ์และตัวเลือกวิธีจัดการข้อผิดพลาดที่เฉพาะเจาะจงจะถูกปล่อยให้เป็นฟังก์ชันระดับสูงกว่า ( high_level_ABS)


7

ฟังก์ชันรีสตาร์ทมีความสำคัญมากใน R ที่สืบทอดมาจาก Lisp จะมีประโยชน์หากคุณต้องการเรียกใช้ฟังก์ชันบางอย่างในร่างกายของลูปและคุณเพียงแค่ต้องการให้โปรแกรมดำเนินการต่อหากการเรียกฟังก์ชันยุบลง ลองใช้รหัสนี้:

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(){})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.