显式调用`[.data.table`函数

3
我发现一个奇怪的问题,在另一台机器上运行我的 R 程序时。当我尝试运行 data.table 的 join 操作 df1[df2] 时,会报错:

Error in `[.default`(x, i) : invalid subscript type 'list'

我猜测是因为在另一台机器上,R 环境找不到 data.table 的方括号函数(尽管我已经加载了库)。
为了强制 R 使用 data.table 的方括号函数,我想显式地调用该函数,但我不知道如何操作。
以下是我尝试过的方法。
library(data.table)    
df1 <- data.frame(a = c("a1","a2","a3"), n = c(1,2,3), b = c(T,T,T))
df2 <- data.frame(a = c("a1","a2","a3"), n = c(1,2,3), b = c(F,T,F))

df1 <- data.table(df1)
df2 <- data.table(df2)
setkey(df1,a,n,b)
setkey(df2,a,n,b)

df1[df2] # produces `[.default`(x, i) : invalid subscript type 'list'

# my tries to call `[.data.table` explicitly all produce errors
`[.data.table`(df1, df2)
data.table::`[.data.table`(df1, df2)
data.table::`[`(df1, df2)

我该如何显式地使用data.table包中的括号函数(bracket function)?

编辑:

好的,我试图找到错误的根本原因。我正在使用R版本3.2.1。

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] data.table_1.9.2 mypackage_1.0    ROracle_1.1-10   DBI_0.2-7

loaded via a namespace (and not attached):
[1] plyr_1.8.1    reshape2_1.4  Rcpp_0.11.2   stringr_0.6.2

is.data.table 会在调用 df1[df2] 之前同时在 df1 和 df2 上返回 TRUE (我是通过代码进行调试的)。

包含代码行 df1[df2] 的函数位于 mypackage_1.0 中(我正在开发一个包)。我注意到,如果逐行运行代码,而不是调用我的包函数并进行调试,则代码能够按预期工作。因此,我认为包中可能存在问题。在 DESCRIPTION 文件中,我仅在“建议”下导入了 data.table 包。这可能与此有关吗?


5
不,调查错误发生的原因。从错误信息来看,我会认为df1不是一个数据表格(data.table)。请提供你的sessionInfo。(我在我的机器上无法重现这个错误。) - Roland
2
另外,在运行 df1[df2](在您的真实数据集上)之前,请检查 is.data.table(df1) 的输出。我有一种感觉,您在这里打错了一些字。顺便说一下,您可以直接创建并设置 data.table 的键。尝试使用 df1 <- data.table(a = c("a1","a2","a3"), n = c(1,2,3), b = c(T,T,T), key = "a,n,b") - David Arenburg
1
但是你尝试制作可重现的示例的努力值得肯定。我无法重现这个错误。猜测可能是在从数据框创建数据表时,您输入了dt1dt2而不是df1df2。也许可以使用setDT(df1)函数来代替? - Simon O'Hanlon
@Roland、David、Simon,感谢你们的回复,我已经按照你们的建议进行了操作,并对问题进行了编辑。 - Fabian Braun
2
将 data.table 从“Suggests”移动到“Depends”部分的 DESCRIPTION 文件中解决了该问题。 - Fabian Braun
显示剩余2条评论
1个回答

3

由于评论内容过长,所以我将其作为回答发布。
以下是与您的情况相关的一般性评论。

  1. 您可以使用:::运算符显式调用未导出的data.table函数来显式调用[.data.table

data.table:::`[.data.table`(x, i)

使用:::不是最佳实践,因为它使您负责一个包作者决定不直接向用户公开的函数。您应该记住这一点,但是R CMD check不会引发错误或警告。根据编写R扩展

使用foo:::f而不是foo::f允许访问未导出的对象。这通常不被推荐,因为未导出对象的语义可能会在常规维护中由包作者更改。

在我看来,如果您开发了一个将与明确声明的依赖项版本一起部署的内部包,则使用:::是相当安全的。

  1. 更新您的data.table版本,1.9.2已经是相当旧的版本了。
  2. 在您的DESCRIPTION文件中使用Imports data.table,并不要忘记在NAMESPACE文件中定义导入内容
  3. 使用以下方法调试您的有问题的机器

if(is.data.table(df1) && is.data.table(df2)) df1[df2] else stop("not a data.table")
  1. 在调试跨包问题时,使用sessionInfo()作为您的第一步来跟踪已连接的包。

我将接受这个答案作为我的初始问题的有效答案。感谢额外的建议。请注意,我通过将data.table从“Suggests”移动到我的软件包的DESCRIPTION文件的“Depends”部分来解决了我的问题。 - Fabian Braun
以前从未了解过 ::: 的区别,感谢您的提示。 - MichaelChirico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接