2017-08-02 20:42:11
stop()函数退出执行warning()函数显示潜在问题suppressWarnings()函数屏蔽警告message()将运行中的重要信息提示给用户suppressMessage()函数屏蔽提醒信息错误
mean(a)
Error in mean(a) : object 'a' not found
警告
log(-1)
Warning in log(-1) : NaNs produced [1] NaN
提醒
library(epiR)
Package epiR 0.9-87 is loaded Type help(epi.about) for summary information
Fred Brooks: Much of the essence of building a program is in fact the debugging of the specification.
f1逐级调用低级函数,构成一个调用堆栈(call stack)traceback()在堆栈中回溯f1 <- function(x1) f2(x1) f2 <- function(x2) f3(x2) f3 <- function(x3) f4(x3) f4 <- function(x4) f5(x4) f5 <- function(x5) "A" + x5 f1(1)
Error in "A" + x5 : non-numeric argument to binary operator
点"Show Traceback",或traceback()
traceback()
5: f5(x4) at #1 4: f4(x3) at #1 3: f3(x2) at #1 2: f2(x1) at #1 1: f1(1)

debug()函数 (事后要undebug())包括5个按钮:
n/F10): 执行函数的下一步s/Shift+F4): 类似Next,但如下一步是个函数,则进入该函数逐行调试f/Shift+F6): 完成执行当前循环块或函数c/Shift+F5): 结束调试并完成执行剩余的代码结束(Stop, Q/Shift+F8): 退出调试和执行,返回全局环境
Error in "A" + x5 : non-numeric argument to binary operator Called from: f5(x4) Browse[1]> n
getOption("error")
## NULL
browser,则遇错自动进入动态调试options(error = browser)
browseOnce <- function() {
old <- getOption("error")
function() {
options(error = old)
browser()
}
}
options(error = browseOnce())Error in "A" + x5 :
non-numeric argument to binary operator
Called from: f5(x4)
Browse[1]> recover()
Enter a frame number, or 0 to exit
1: f1(1)
2: #1: f2(x1)
3: #1: f3(x2)
4: #1: f4(x3)
5: #1: f5(x4)
6: #1: (function ()
{
.rs.breakOnError(TRUE)
})()
7: .rs.breakOnError(TRUE)
8: eval(substitute(browser(skipCalls = pos),
list(pos = (length(sys.frames()) - frame) + 2)),
envir = sys.frame(frame))
...dump_and_quit <- function() {
# 调试信息写入last.dump.rda
dump.frames(to.file = TRUE)
# 以出错状态退出R
q(status = 1)
}
options(error = dump_and_quit)
load("last.dump.rda")
debugger()browserbrowser()插入到第一行,即相当于运行时debug()debug()函数正是这么做的f <- function(x){
if (1 %in% x){
browser()
return("There is 1")
}else{
return("There is no 1")
}
}
f(1:4)
Called from: f(1:4)
Browse[1]> x
[1] 1 2 3 4
Browse[1]> n
debug at #4: return("There is 1")
Browse[2]> n
[1] "There is 1"options(warn=2)message2error <- function(code) {
withCallingHandlers(code, message = function(e) stop(e))
}
f <- function() message("yup")
message2error(f())
Error in message("yup") : yup出现错误默认整体退出,不返回结果
f <- function(x){
log(x)
2
}
f("1")
Error in log(x) : non-numeric argument
to mathematical function
try捕捉到的错误结果属于"try-error"类
class(try(log("1")))
[1] "try-error"
try()可捕捉错误信息,并继续执行代码
f <- function(x, ...){
try(log(x), ...)
2
}
f("1")
Error in log(x) : non-numeric argument
to mathematical function
[1] 2
try(..., silent=TRUE)隐藏错误信息
f("1", silent=TRUE)
[1] 2
tryCatch(expr, ..., finally)
tryCatch不但能捕捉错误,还提供了一个异常处置框架举个例子:
show_cond <- function(expr, ...){
tryCatch(expr,
error=function(cond) "error",
warning=function(cond) "warn",
message=function(cond) "msg",
finally=cat("The output: "))
}show_cond(log(10))
The output: [1] 2.302585
show_cond(message("!"))
The output: [1] "msg"
show_cond(log(-1))
The output: [1] "warn"
show_cond(log("1"))
The output: [1] "error"
f1 <- function() f2()
f2 <- function() stop("Stop!")
tryCatch(f2(), error=function(e)
print(sys.calls()))
[[1]] tryCatch(f2(), error = function(e)
print(sys.calls()))
[[2]] tryCatchList(expr, classes,
parentenv, handlers)
[[3]] tryCatchOne(expr, names, parentenv,
handlers[[1L]])
[[4]] value[[3L]](cond)withCallingHandlers(f2(), error=function(e)
print(sys.calls()))
[[1]] withCallingHandlers(f2(),
error = function(e) print(sys.calls()))
[[2]] f2()
[[3]] stop("Stop!")
[[4]] .handleSimpleError(function (e)
print(sys.calls()), "Stop!", quote(f2()))
[[5]] h(simpleError(msg, call))
Error in f2() : Stop!condition <- function(subclass, message,
call = sys.call(-1), ...) {
structure(
class = c(subclass, "condition"),
list(message = message, call = call),
...
)
}
err.neg <- condition(
c("neg_error", "error"), "Cannot be negative!")
wrn.zero <- condition(
c("zero_warn", "warning"), "Cannot be zero!")
msg.greet <- condition(
c("greet_msg", "message"), "Bingo!")
newLog <- function(x){
if (x<0) stop(err.neg)
else if (x==0) warning(wrn.zero)
else message(msg.greet)
return(log(x))
}
tryCatch(newLog(1))
Bingo![1] 0
tryCatch(newLog(-1))
Error: Cannot be negative!
tryCatch(newLog(bb))
Error in newLog(bb) : object 'bb' not found
墨菲定律(Murphy's Law): 凡是可能出错的事,准会出错。
match.arg + if/stop 或 stopifnotf <- function(x, fun=c("mean", "median")){
# 确保x是纯数值
stopifnot(all(sapply(x, is.numeric)))
# 确保fun只能是列表中规定的三个
fun <- match.arg(fun)
switch(fun, mean=lapply(x, mean),
median=lapply(x, median),
var=lapply(x, var))
}
f(1:10, "sum")
Error in match.arg(fun) : 'arg' should be
one of “mean”, “median”, “var”f <- function(x, fun=c("mean", "median")){
library(assertthat)
assert_that(all(sapply(x, is.numeric)))
fun <- match.arg(fun)
switch(fun, mean=lapply(x, mean),
median=lapply(x, median),
var=lapply(x, var))
}
f(list(1:10, 11:20, "a"), "mean")
Error: Elements 3 of sapply(x, is.numeric)
are not truesubset、transform、with
substitute、quote、parse、eval等函数自定义非标准求值函数f1 <- function(df, cond)
df[cond,]
f1(mtcars, mtcars$mpg>33)
mpg cyl disp hp drat ... carb Toyota Corolla 33.9 4 71.1 65 4.22 ... 1
f2 <- function(df, cond)
subset(df, cond)
f2(mtcars, mpg>33)
Error in eval(e, x, parent.frame()) :
object 'mpg' not found意外降维: [
getCol <- function(df, i) df[,i] getCol(mtcars[,1], 1)
Error in df[, i] : incorrect number of dimensions
sapply(mtcars[1:8, 1], mean)
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4
结构变异: sapply
sapply(integer(), identity)
list()
避免降维: drop=FALSE,simplify=FALSE
getCol <- function(df, i) df[, i, drop=FALSE] getCol(mtcars[, 1, drop=FALSE], 1)
sapply(mtcars[1:8, 1, drop=FALSE], mean)
保障数据结构: 用vapply代替sapply
vapply(integer(), identity, 0L)
integer(0)
vapply(list(c(1, 2), c(1, 3, 1)),
function(v) which(v==1), 0)
Error in vapply(list(c(1, 2), c(1, 3, 1)),
function(v) which(v == 1), :
values must be length 1,
but FUN(X[[2]]) result is length 2rlog <- function(x) lapply(x,log); rlog(list(1:4,"a"))
Error in FUN(X[[i]], ...) : non-numeric
argument to mathematical function
rlog <- function(x) lapply(x, function(v)
tryCatch(log(v), error=function(cdt) NULL))
rlog(list(1:4, "a"))
[[1]] [1] 0.0000000 0.6931472 1.0986123 1.3862944 [[2]] [1] NULL
Thank you!