【问题标题】:Using data.table package inside my own package在我自己的包中使用 data.table 包
【发布时间】:2012-05-18 14:47:55
【问题描述】:

我正在尝试在我自己的包中使用 data.table 包。 MWE如下:

我创建了一个函数 test.fun,它只是创建了一个小的 data.table 对象,然后将“A”列分组的“Val”列相加。代码是

test.fun<-function ()
{
    library(data.table)
    testdata<-data.table(A=rep(seq(1,5), 5), Val=rnorm(25))
    setkey(testdata, A)
    res<-testdata[,{list(Ct=length(Val),Total=sum(Val),Avg=mean(Val))},"A"]
    return(res)
}

当我在常规 R 会话中创建此函数,然后运行该函数时,它按预期工作。

> res<-test.fun()
data.table 1.8.0  For help type: help("data.table")
> res
     A Ct      Total        Avg
[1,] 1  5 -0.5326444 -0.1065289
[2,] 2  5 -4.0832062 -0.8166412
[3,] 3  5  0.9458251  0.1891650
[4,] 4  5  2.0474791  0.4094958
[5,] 5  5  2.3609443  0.4721889

当我将此函数放入一个包中,安装包,加载包,然后运行该函数时,我收到一条错误消息。

> library(testpackage)
> res<-test.fun()
data.table 1.8.0  For help type: help("data.table")
Error in `[.data.frame`(x, i, j) : object 'Val' not found

谁能向我解释为什么会发生这种情况以及我可以做些什么来解决它。非常感谢任何帮助。

【问题讨论】:

  • 我猜你没有声明依赖。你应该从你的函数中删除library(data.table),并在你的命名空间和DESCRIPTION中声明depends:data.table
  • 现在还有.datatable.aware = TRUE 选项来处理此问题,如this 问题和下面链接的vignette 中所述。声明Depends: data.table 会将整个包附加到搜索路径,有时是discouraged

标签: r data.table


【解决方案1】:

Andrie 的猜测是正确的,+1。上面有一个常见问题解答(参见vignette("datatable-faq")),还有一个关于导入data.table 的新vignette

FAQ 6.9:我创建了一个依赖于 data.table 的包。我如何能 确保我的包是 data.table-aware 以便继承 data.frame 有效吗?

i) 在您的说明文件的 Depends: 字段中包含 data.table,或 ii) 在您的说明文件的 Imports: 字段中包含 data.table 并在您的 NAMESPACE 文件中包含 import(data.table)

更多背景... 在[.data.table(和其他data.table 函数)的顶部,您会看到一个取决于调用cedta() 的结果的开关。这代表调用环境数据表感知。输入data.table:::cedta 揭示了它是如何完成的。它依赖于具有命名空间的调用包,并且该命名空间导入或依赖于data.table。这就是如何将data.table 传递给非data.table-aware 包(例如base 中的函数),并且这些包可以在data.table 上使用绝对标准的[.data.frame 语法,幸福地没有意识到data.frame is() 也是data.table

这也是为什么data.table 继承不能与无命名空间包兼容的原因,以及为什么根据用户要求我们必须要求此类包的作者在他们的包中添加一个命名空间以使其兼容。幸运的是,现在 R 为缺少一个的包添加了一个默认命名空间(从 v2.14.0 开始),这个问题已经消失了:

R 版本 2.14.0 中的更改
* 所有包都必须有一个命名空间,如果源中没有提供,则在安装时创建一个。

【讨论】:

  • (很抱歉恢复这个,但是......)马修,你能从交互的角度解释一下这是如何工作的吗?如果我的包在交互式会话中向用户返回data.table,他们是否需要使用data.table 语义,或者有什么方法可以支持熟悉的data.frame 语法?
  • @JeffAllen 那是一个新的……不确定。如果您的包取决于 data.table 那么我猜这将使用户 data.table 知道。也许 Importing data.table 不会(也许这就是你想要的)。
  • 谢谢马特!经过半天的失败和搜索,这解决了我的问题。我只将 data.table 放在 Imports 中。该代码在 R 中运行良好,但在包中却不行。移到 Depends 并且它有效!
  • @OskarHansson Glad Depends 工作,但 Import 应该工作,只要你有 both 在 DESCRIPTION NAMESPACE 中的import(data.table) 的导入?
  • @MattDowle 你是对的。我在使用 Depends 时收到了一条注释。我改回 Imports + 在代码中添加了 @import data.table,因此 Roxygen 在 NAMESPACE 中添加了 import(data.table)
【解决方案2】:

这是完整的食谱:

  1. 在您的DESCRIPTION 文件中将data.table 添加到Imports

  2. @import data.table 添加到您各自的 .R 文件(即,包含您的函数的 .R 文件,该文件引发了错误 Error in [.data.frame(x, i, j) : object 'Val' not found)。

  3. 输入 library(devtools) 并将工作目录设置为指向 R 包的主目录。

  4. 输入document()。这将确保您的 NAMESPACE 文件包含 import(data.table) 行。

  5. 输入build()

  6. 输入install()

如需了解 build()install() 的功能,请参阅:http://kbroman.org/pkg_primer/

然后,一旦你关闭你的 R 会话并下次登录,你就可以立即进入:

  1. 输入library("my_R_package")

  2. 输入上述 .R 文件中的函数名称。

  3. 享受吧!你不应该再收到可怕的Error in [.data.frame(x, i, j) : object 'Val' not found

【讨论】:

  • 我按照这些说明操作并收到function not found。我找不到类似的东西,所以我创建了一个问题stackoverflow.com/questions/56720520/…
  • 谢谢你。您以一种易于阅读的格式帮助我了解了该做什么。
猜你喜欢
  • 2021-09-09
  • 1970-01-01
  • 2019-12-06
  • 2019-03-08
  • 1970-01-01
  • 2019-03-01
  • 2020-10-29
相关资源
最近更新 更多