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

data.table和使用try语句的错误处理,r,data.table,R,Data.table,我试图在我的R代码中加入一些错误处理 伪代码如下: 目的是检查函数foo是否在X和Y的某些组合中引发错误。如果它确实引发了一个错误,那么我想跳过最终结果数据帧中的记录组合。我试过以下方法,但运气不太好: 我总是可以尝试在foo周围编写一个包装器来执行错误检查,但是我正在寻找一种直接在data.table调用中编写语法的方法。这可能吗 提前谢谢你的帮助 这里有一个虚拟函数和数据: foo = function(X,Y) { if (any(Y==2)) stop("Y contai

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

伪代码如下:



目的是检查函数
foo
是否在
X
Y
的某些组合中引发错误。如果它确实引发了一个错误,那么我想跳过最终结果数据帧中的记录组合。我试过以下方法,但运气不太好:



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


提前谢谢你的帮助

这里有一个虚拟函数和数据:

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
一步一步:

> DT[, c := foo(a,b), by=a ]
Error in foo(a, b) : Y contains 2!
好的,那是建筑。好

旁白:尽管有错误,还是添加了
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
只填充了第一个成功的组;它停在第二组。这是故意的。在将来的某个时候,我们可以向
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)
更好的是,长期的错误已经过去了。但是为什么仍然是来自
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
哦,原来是这样。第三组已运行,值9和18显示在第3行和第6行中。查看
?try
会显示
静默的
参数

> 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
>DT[,c:={
if(继承)try(ans#无错误
>DT
a、b、c
1: 1 1  1
2:22 NA
3: 3 3  9
4: 1 4  4
5:25 NA
6: 3 6 18

您可能会发现plyr中的一个函数在这里很有用-它完全概括了Matt所做的工作,但以简洁和可重用的方式:
failwith()

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

failwith
的定义非常简单:

failwith <- function(default = NULL, f, quiet = FALSE) {
  f <- match.fun(f)
  function(...) {
    try_default(f(...), default, quiet = quiet)
  }
}

从概念上讲,处理这种类型的错误应该是传递给DATA表的函数的责任。Matt -辉煌解决方案。谢谢C++的详细回答。
> 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
> 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
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 ]
failwith <- function(default = NULL, f, quiet = FALSE) {
  f <- match.fun(f)
  function(...) {
    try_default(f(...), default, quiet = quiet)
  }
}