为什么data.table行过滤可以在不引发错误的情况下静默接受函数中缺少的参数?

时间:2019-04-25 13:58:03

标签: r data.table

在将数据表对象DT和范围作为输入的函数中,如果范围仅用于过滤DT的行,则该函数运行时不会引发错误。

我的测试套件中有一个函数失败,因为它返回的数据帧大小与预期的不同。根本原因是我忽略了range参数。

因为这是我几年前编写的代码,所以我不确定哪个测试期望和代码正确。 (纸上都在做他们应该做的事情)。 使我走上正轨的唯一一件事就是没有错误的缺少参数。

最小示例:

library(data.table)

data <- data.table(iris)
select_range <- function(DT, range) {
    DT[range, ]
}

select_range(data) 

最后一次调用返回完整数据,而我期望缺少参数会出错。

range表达式使用DT[range, ]时,这种行为怎么可能? 有什么建议可以避免这种令人惊讶的影响?

1 个答案:

答案 0 :(得分:2)

您遇到的问题是,缺少第一个(或第二个)参数时,[不会引发错误。 data.table位无关紧要-对数据帧的工作方式相同,因此为简单起见,我将使用数据帧作为示例。 iris[,]返回整个数据帧,而当缺少range参数时,这也是您得到的结果。

针对您的情况,一种解决方法是显式检查参数:

select_range <- function(DT, range) {
    if(missing(range)) stop("range must be specified")
    DT[range, ]
}

如注释中所建议,如果未指定范围,您还可以使用诸如NA0之类的默认值来返回空数据框。

一个人可能会问为什么,当未定义range时,DT[range, ]在函数内部起作用,而在交互式使用时,iris[range, ]会引发错误(Error in xj[i] : invalid subscript type 'builtin',因为它是尝试使用内置的range()函数),或者如果我们仅使用未定义的名称iris[askdfj, ]则会得到Error in [。data.frame (iris, askdfj, ) : object 'askdfj' not found。我没有研究[的C代码,但是大概它必须检查参数的缺失,就像上面我的建议一样。但是,如果缺少该参数,则不会抛出错误,而是默认为所有行。 missing()(与[类似,它是一个.Primitive C函数,它告诉是否指定了参数,但不检查是否已定义规范。如果运行我的{ {1}}将未定义的对象传递到select_range arg,例如range,因此select_range(iris, kkjfdfk)行的值为missing,因此不会导致错误。错误来自下一行。