R语言tryCatch使用方法:判断Warning和Error

育种技术 农业技术
邓飞    2021-01-27    567

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打印出来,也可以执行其它命令
})

「示意图如下:」图片.png

3. 走两步试试?

下面用一个示例,看一下tryCatch是怎么使用的。

首先看一下R中warning的报警信息:

「warning」

# 示例数据
library(data.table)
dd = data.frame(ID = 1:10,y= rnorm(10))
dd

# warning
re1 = dcast(dd,y~.)
re1
> 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
# 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

「结果如下:」

> 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

结果如下:

> 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

「代码:」

re1 = tryCatch({
  # dcast(dd,y~.) # warning
  # aaaaa # error
  melt(dd,y~.)

},warning = function(w){
  print("warning")
  2

},error = function(e){
  print("error")
  3
})
re1

「运行结果:」

> 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

所以呢,要注意上面的情况,有时候warningerror同时存在时,warning的优先级是靠前的。

5. 顺利上岸

上岸过程见3. 走两步试试?

6. 被借鉴的文章

http://www.mazamascience.com/WorkingWithData/?p=912 https://sarahpenir.github.io/r/Warning-and-Error-Handling-with-trycatch/

本文来自微信公众号【育种数据分析之放飞自我】公众号ID:R-breeding;未经许可谢绝二次转载至其他网站。

本文为专栏作者授权科易网发表,版权归原作者所有。文章系作者个人观点,不代表科易网立场,转载请联系原作者。如有任何疑问,请联系ky@1633.com。
热门观点