1. 出门掉坑里
因为一些情况,需要判断一行命令运行的状态,然后再做出反应,整体来说:
- 是否出现warning,出现了怎么处理?
- 是否出现Error,出现了怎么处理?
- 没有出现怎么处理?
R中判断warning和error状态的函数,我没有找到。一个玩Java
的同事说,try.....catch
多经典的方法,你怎么不用呢?
❝我知道R中有
tryCatch
这个函数,但是没有具体用过。我一直把R语言当作科学计算语言,没有当成编程语言,伪程序员的气质从没有用过tryCatch
表现出来了。当然,我不会说这是我的问题,我会甩锅,都是R语言
的锅,它根本不是编程语言……。 ❞❝吐槽完毕,我还是要从编程的角度学习
R语言
,正所谓脑子一堆粪,看什么都是粪
说的就是我啊,一直把R语言当做高级计算器,怎么能知道R语言的编程功能呢!
。既然已经用到了,那我就研究一下它的用法,然后用个示例,解释一下它的用法,希望对后来者有用。 ❞
2. 梯子怎么用?
「tryCatch
的整体逻辑:」
tryCatch({
命令
}, warning = function(w){
# 这里是出现warning状态时,应该怎么做,可以用print打印出来,可以执行其它命令
}, error = function(e){
# 这里时出现Error状态时,应该怎么做,可以用print打印出来,也可以执行其它命令
},finally = {
# 这是运行正常时,应该怎么做,可以用print打印出来,也可以执行其它命令
})
「示意图如下:」
3. 走两步试试?
下面用一个示例,看一下tryCatch
是怎么使用的。
首先看一下R中warning
的报警信息:
「warning」
代码语言:javascript复制# 示例数据
library(data.table)
dd = data.frame(ID = 1:10,y= rnorm(10))
dd
# warning
re1 = dcast(dd,y~.)
re1
代码语言:javascript复制> re1 = dcast(dd,y~.)
Using 'y' as value column. Use 'value.var' to override
Warning message:
In dcast(dd, y ~ .) :
The dcast generic in data.table has been passed a data.frame and will attempt to redirect to the reshape2::dcast; please note that reshape2 is deprecated, and this redirection is now deprecated as well. Please do this redirection yourself like reshape2::dcast(dd). In the next version, this warning will become an error.
可以看到,代码执行成功了,但是会给出Warning message
然后我们看一下Error
的报警信息,假定R中没有aaaaa
的对象,你直接打印出来,会报错:
# error
aaaaa
代码语言:javascript复制> # error
> aaaaa
错误: 找不到对象'aaaaa'
那我们用tryCatch
走两步看看?
「warning处理代码」
- 在代码中,写下warning的语句,在
warning
的条件下,返回2
- 在代码中,写下error的语句,在
error
的条件下,返回3
re1 = tryCatch({
dcast(dd,y~.) # warning
# aaaaa # error
},warning = function(w){
2
print("warning")
},error = function(e){
3
print("error")
})
re1
「结果如下:」
代码语言:javascript复制> re1 = tryCatch({
dcast(dd,y~.) # warning
# aaaaa # error
},warning = function(w){
print("warning")
2
},error = function(e){
print("error")
3
})
[1] "warning"
> re1
[1] 2
可以看到,因为dcast(dd,y~.) # warning
返回warning
,所以会执行function(w){}
的内容,即re1 = 2
,同时打印出warning
.
「error处理代码」
如果我们执行error
的代码,那么他就re1=3
,同时打印出error
re1 = tryCatch({
# dcast(dd,y~.) # warning
aaaaa # error
},warning = function(w){
print("warning")
2
},error = function(e){
print("error")
3
})
re1
结果如下:
代码语言:javascript复制> re1 = tryCatch({
# dcast(dd,y~.) # warning
aaaaa # error
},warning = function(w){
print("warning")
2
},error = function(e){
print("error")
3
})
[1] "error"
> re1
[1] 3
可以看到,打印出了error
的警告,同时,re1赋值为了3
。
4. 意料之外的判断
我有一个大胆的想法,如果一个程序,既有warning
,又有error
怎么办?
一般情况下,是不会存在这种情况的,但是如果有,R语言是如何处理的呢?
「看示例:」melt这个函数,运行melt(dd,y~.)
会报错,同时,因为这个函数在data.table
用法有变化,因此,也会给出warning
信息。
> # 既有warning,又有error时,以warning为主
> melt(dd,y~.)
Error in match(x, y, 0L) : 'match'需要矢量参数
此外: Warning message:
In melt(dd, y ~ .) :
The melt generic in data.table has been passed a data.frame and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(dd). In the next version, this warning will become an error.
「这个时候,如果用tryCatch
,它会捕捉到warning
,而不是error
」
「代码:」
代码语言:javascript复制re1 = tryCatch({
# dcast(dd,y~.) # warning
# aaaaa # error
melt(dd,y~.)
},warning = function(w){
print("warning")
2
},error = function(e){
print("error")
3
})
re1
「运行结果:」
代码语言:javascript复制> re1 = tryCatch({
# dcast(dd,y~.) # warning
# aaaaa # error
melt(dd,y~.)
},warning = function(w){
print("warning")
2
},error = function(e){
print("error")
3
})
[1] "warning"
> re1
[1] 2
所以呢,要注意上面的情况,有时候warning
和error
同时存在时,warning
的优先级是靠前的。
5. 顺利上岸
上岸过程见3. 走两步试试?
6. 被借鉴的文章
❝http://www.mazamascience.com/WorkingWithData/?p=912 https://sarahpenir.github.io/r/Warning-and-Error-Handling-with-trycatch/ ❞