【问题标题】:R data.table ':=' works in direct call, but same function in a package failsR data.table ':=' 在直接调用中有效,但包中的相同功能失败
【发布时间】:2015-03-14 20:57:46
【问题描述】:

使用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

这行得通:

myFunc = function(instruction) {
eval(parse(text=instruction))
}
myFunc(instruction)
#   name
#1:    1
#2:    2
#3:    3

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

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(":=").

为什么?


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

此外,data.table 的所有其他内容在函数中都可以正常工作,只是 := 运算符不行。

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

【问题讨论】:

  • 您是否遵循了FAQ 6.9 中的建议?此外,不鼓励使用eval(parse())
  • @Roland Add data.table to Depends 解决了它......但导致一个问题:我的包实际上并不依赖于 data.table;事实上,这完全不相关。在这个例子中,它只有一个函数,myFunc——没有 data.table 任何东西。但它不能与 data.table 一起使用而不将其添加到 Depends...
  • 你的包有eval(parse(text=instruction))instruction可以是任何东西!在评估时,instruction 要求的任何功能都必须可用;这应该在您的包裹的使用说明中指定。当instruction 需要data.table 中的函数时,您会看到这一点;在执行myFuncInPackage(instruction)之前加载'data.table'并查看它是否有效。
  • @Sergii Zaskaleta 不...我没有在我的函数中使用:=。这是由用户在“指令”变量中传递的。它与包裹无关...
  • @sheffien 你能检查一下你是否将NAMESPACE 文件更新为import(data.table)DESCRIPTION 更新为Imports: data.table?我最近遇到了同样的问题,只是因为NAMESPACE 文件中缺少条目。

标签: r data.table colon-equals


【解决方案1】:

我遇到了同样的问题,我将data.table 添加到ImportsDepends: 解决了它。我的data.table 版本是1.9.6

【讨论】:

  • 你能举个例子吗? - - 我有一个脚本,它提供了一个使用data.table 的函数。我在这里得到错误。我在脚本和/或函数本身中包含library(data.table)。 - - 你能否也举个例子,你如何在这里应用ImportsDepends:来解决问题。我的 data.table 是 1.10.4。
  • 它在 R 包上下文中对我有用 - 而不是原始脚本。但回答您的问题 - 您可以在DESCRIPTION 文件中应用它:Imports: data.table (>= 1.9.6) Depends: data.table (>= 1.9.6) ,例如:pastebin.com/uy10Devh
  • 你能阻止包被这样的规范加载吗?等imports data.table,但防止reshape2作为自己的包加载。
  • 您只能使用@import从包中加载特定功能,例如:@importFrom jsonlite toJSON unbox。在这里阅读更多:kbroman.org/pkg_primer/pages/depends.html
  • 就我而言,只需在DESCRIPTION 文件中提及Imports: data.table 就足够了。更重要的是,在Depends: 部分再次提及会触发来自devtools::check() 的注释 - Package listed in more than one of Depends, Imports, Suggests, Enhances: data.table A package should be listed in only one of these fields.
【解决方案2】:

我终于找到了这个问题的答案(几年后)。所有 cmets 和答案都建议将data.table 添加到DependsImports,但这是不正确的;该包不依赖于data.table,并且假设它可能是任何包,而不仅仅是data.table,这意味着从逻辑上得出结论,该建议需要将所有可能的包添加到Depends——因为该依赖关系由用户提供instruction,而不是包提供的功能。

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

myFunc = function(instruction) {
eval(parse(text=instruction), envir=globalenv())
}

为什么会这样

这会导致eval 函数在搜索路径中包含必要包的环境中完成。

data.table 的情况下,由于函数重载的复杂性,调试起来特别困难。在这种情况下,罪魁祸首实际上不是:= 函数,而是[ 函数。 := 错误是一个红鲱鱼。在撰写本文时,data.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(":=").')

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

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

在我的新包(包含myFuncInPackage)中发生了什么,当它评估代码时,它将[ 函数解析为基本[ 函数而不是data.table 的@987654353 @ 功能。它试图将:= 评估为一个函数,它没有被[ 使用,因为它不是正确的[,所以:= 作为一个函数而不是作为一个值传递给data.table' s,因为data.table 不在命名空间中(或者在search() 层次结构中较低。在此设置中,:= 不被理解,因此它被评估为一个函数,从而触发@987654362 中的错误消息@上面的代码。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    相关资源
    最近更新 更多