在将数据表对象DT和范围作为输入的函数中,如果范围仅用于过滤DT的行,则该函数运行时不会引发错误。
我的测试套件中有一个函数失败,因为它返回的数据帧大小与预期的不同。根本原因是我忽略了range参数。
因为这是我几年前编写的代码,所以我不确定哪个测试期望和代码正确。 (纸上都在做他们应该做的事情)。 使我走上正轨的唯一一件事就是没有错误的缺少参数。
最小示例:
library(data.table)
data <- data.table(iris)
select_range <- function(DT, range) {
DT[range, ]
}
select_range(data)
最后一次调用返回完整数据,而我期望缺少参数会出错。
当range
表达式使用DT[range, ]
时,这种行为怎么可能?
有什么建议可以避免这种令人惊讶的影响?
答案 0 :(得分:2)
您遇到的问题是,缺少第一个(或第二个)参数时,[
不会引发错误。 data.table
位无关紧要-对数据帧的工作方式相同,因此为简单起见,我将使用数据帧作为示例。 iris[,]
返回整个数据帧,而当缺少range
参数时,这也是您得到的结果。
针对您的情况,一种解决方法是显式检查参数:
select_range <- function(DT, range) {
if(missing(range)) stop("range must be specified")
DT[range, ]
}
如注释中所建议,如果未指定范围,您还可以使用诸如NA
或0
之类的默认值来返回空数据框。
一个人可能会问为什么,当未定义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
,因此不会导致错误。错误来自下一行。