使用try语句进行data.table和错误处理

Man*_*noj 6 r data.table

我试图在我的R代码中加入一些错误处理.

下面的伪代码:


foo = function(X,Y) {
...

return(ret.df);
}

DT = DT[,ret.df := foo(X,Y), by=key(DT)];
Run Code Online (Sandbox Code Playgroud)

目的是检查是否有某种组合X,Y该函数foo会引发错误.如果它确实引发了错误,那么我想在最终结果数据帧中跳过该记录组合.我试过下面没有太多运气:


    DT = DT[ ,  try(ret.df = : foo(X,y)); 
    if(not (class(ref.df) %in% "try-error') ) {
        return(ret.df);
    }, by = key(DT) ];
Run Code Online (Sandbox Code Playgroud)

我总是可以尝试编写一个包装器foo来进行错误检查,但是我正在寻找一种直接在data.table调用中编写语法的方法.这可能吗?

感谢您的帮助!

Mat*_*wle 10

这是一个虚拟函数和数据:

foo = function(X,Y) {
    if (any(Y==2)) stop("Y contains 2!")
    X*Y
}
DT = data.table(a=1:3, b=1:6)
DT
   a b
1: 1 1
2: 2 2
3: 3 3
4: 1 4
5: 2 5
6: 3 6
Run Code Online (Sandbox Code Playgroud)

一步步 :

> DT[, c := foo(a,b), by=a ]
Error in foo(a, b) : Y contains 2!
Run Code Online (Sandbox Code Playgroud)

好的,这是建筑.好.

旁白:c尽管有错误,但已添加通知栏.

> DT
   a b  c
1: 1 1  1
2: 2 2 NA
3: 3 3 NA
4: 1 4  4
5: 2 5 NA
6: 3 6 NA
Run Code Online (Sandbox Code Playgroud)

只有第一个成功的小组被填充; 它在第二组停了下来.这是设计的.在将来的某个时候,我们可以在内部添加事务data.table,比如SQL,这样如果发生错误,任何更改都可以回滚.无论如何,只是需要注意的事情.

要处理您可以使用的错误{}.

第一次尝试 :

> DT[, c := {
    if (inherits(try(ans<-foo(a,b)),"try-error"))
        NA
    else
        ans
}, by=a]
Error in foo(a, b) : Y contains 2!
Error in `[.data.table`(DT, , `:=`(c, { : 
  Type of RHS ('logical') must match LHS ('integer'). To check and coerce would
  impact performance too much for the fastest cases. Either change the type of
  the target column, or coerce the RHS of := yourself (e.g. by using 1L instead
  of 1)
Run Code Online (Sandbox Code Playgroud)

错误告诉我们该怎么做.让我们来要挟RHS(类型NA从)logicalinteger.

> DT[, c:= {
    if (inherits(try(ans<-foo(a,b)),"try-error"))
        NA_integer_
    else
        ans
}, by=a]
Error in foo(a, b) : Y contains 2!
Run Code Online (Sandbox Code Playgroud)

更好,长期错误消失了.但为什么还有错误foo呢?我们来看看DT只是为了检查.

> DT
   a b  c
1: 1 1  1
2: 2 2 NA
3: 3 3  9
4: 1 4  4
5: 2 5 NA
6: 3 6 18
Run Code Online (Sandbox Code Playgroud)

哦,它已经奏效了.第3组已经运行,值9和18出现在第3行和第6行.查看?try显示silent参数.

> DT[, c:= {
    if (inherits(try(ans<-foo(a,b),silent=TRUE),"try-error"))
        NA_integer_
    else
        ans
}, by=a]
> # no errors
> DT
   a b  c
1: 1 1  1
2: 2 2 NA
3: 3 3  9
4: 1 4  4
5: 2 5 NA
6: 3 6 18
Run Code Online (Sandbox Code Playgroud)

  • 马特 - 精彩的解决方案..谢谢你这么详细的回复.干杯 (3认同)

had*_*ley 5

有来自plyr,你可能会发现这里很有用的功能-它包扎正是马特做了,但是在简洁和可重用的方式:failwith()

library(data.table)
library(plyr)

foo = function(X,Y) {
    if (any(Y==2)) stop("Y contains 2!")
    X*Y
}
DT = data.table(a=1:3, b=1:6)
DT

DT[, c := failwith(NA_integer, foo)(a,b), by=a ]
Run Code Online (Sandbox Code Playgroud)

failwith接受两个参数:一个用于返回错误的值和一个用于修改的函数f。它返回该版本的新版本f,而不是抛出错误将返回默认值。

的定义failwith非常简单:

failwith <- function(default = NULL, f, quiet = FALSE) {
  f <- match.fun(f)
  function(...) {
    try_default(f(...), default, quiet = quiet)
  }
}
Run Code Online (Sandbox Code Playgroud)