R data.table':='在直接调用中工作,但是包中的相同功能失败

nsh*_*eff 10 r data.table colon-equals

使用R的data.table包,

这有效:

instruction = "a = data.table(name=1:3, value=1:3, blah=1:3); a[,c('value', 'blah'):=NULL]"
eval(parse(text=instruction))
#   name
#1:    1
#2:    2
#3:    3
Run Code Online (Sandbox Code Playgroud)

这有效:

myFunc = function(instruction) {
eval(parse(text=instruction))
}
myFunc(instruction)
#   name
#1:    1
#2:    2
#3:    3
Run Code Online (Sandbox Code Playgroud)

现在,将此函数放入包中,加载它,然后尝试调用它.这不起作用:

myFuncInPackage(instruction)
#Error in `:=`(c("value", "blah"), NULL) : 
#  Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").
Run Code Online (Sandbox Code Playgroud)

为什么?


编辑:@Roland指出在包Depends字段中添加data.table 使它工作.但是,我不认为这是一个很好的解决方案,因为该软件包并不真正依赖,要求或使用data.table.我只是希望能够在包中使用data.table.

此外,data.table的所有其他功能在函数中运行良好,而不是:=运算符.

所以我想一个后续问题可能是:我应该将data.table添加到我编写的每个包的Depends中,以便data.tables在该包的函数中按预期工作吗?这似乎不正确......解决这个问题的正确方法是什么?

nsh*_*eff 6

我终于找到了这个问题的答案(几年后)。所有评论和答案都建议添加data.tableDependsImports,但这是不正确的;该包不依赖于,data.table并且假设可以是任何包,而不仅仅是 data.table,这意味着采取合乎逻辑的结论,该建议需要将所有可能的包添加到Depends- 因为该依赖是由提供 的用户提供的instruction,而不是通过包提供的功能。

相反,基本上是因为调用eval是在包的命名空间内完成的,这不包括其他包提供的功能。我最终通过在eval调用中指定全局环境来解决这个问题:

myFunc = function(instruction) {
eval(parse(text=instruction), envir=globalenv())
}
Run Code Online (Sandbox Code Playgroud)

为什么这有效

这会导致eval在搜索路径中包含必需包的环境中完成该功能。

在这种data.table情况下,由于函数重载的复杂性,调试特别困难。在这种情况下,罪魁祸首实际上不是:=函数,而是[函数。该:=错误是红鲱鱼。在撰写本文时,:=函数 indata.table定义如下:

https://github.com/Rdatatable/data.table/blob/348c0c7fdb4987aa6da99fc989431d8837877ce4/R/data.table.R#L2561

":=" <- function(...) stop('Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").')

就是这样。这意味着:任何对:=as 函数的调用都会因错误消息而停止,因为这不是作者打算:=使用的方式。相反,:=实际上只是由 中的[函数解释的关键字data.table

但是这里会发生什么:如果[函数没有正确映射到 指定的版本data.table,而是映射到 base [,那么我们就会遇到问题——因为它无法处理:=,所以它被视为一个函数并触发错误信息。所以罪魁祸首是[.data.table——重载的括号运算符。

发生的事情发生在我的新包中(包含myFuncInPackage),当它去评估代码时,它将[函数解析为基[函数而不是 todata.table[函数。它试图:=作为一个函数求值,它没有被 消耗,[因为它不是正确的[,所以:=作为函数而不是作为值传递给data.tables,因为data.table它不在命名空间中(或在search()层次结构中较低). 在这个设置中,:=不被理解,所以它被评估为一个函数,从而触发了data.table上面代码中的错误信息。

当您指定 eval 在全局环境中发生时,它会正确地将[函数解析为[.data.table,并且:=被正确解释。

顺便说一句,如果您传递的不是字符串而是代码块(更好)到eval()包内部,您也可以使用它:

eval(substitute(instruction), envir=globalenv())

在这里,substitute防止instruction在参数评估阶段在包命名空间内解析(错误),以便它完整地返回 globalenv,在那里可以使用所需的函数正确评估它。


Taz*_*Taz 5

我有同样的问题,我解决它添加data.tableImportsDepends:.我的data.table版本是1.9.6

  • 它在R包上下文中对我有用 - 而不是原始脚本.但回答你的问题 - 你可以在`DESCRIPTION`文件中应用它:`Imports:data.table(> = 1.9.6)取决于:data.table(> = 1.9.6)`,例如:https:// pastebin .COM/uy10Devh (2认同)