我在将data.table用于roxygen2导出函数时遇到问题。
这是一个名为foo.R的文件中的一个简单假函数(位于我的软件包的R目录中),它使用data.table:
#' Data.table test function
#' @export
foo <- function() {
m <- data.table(c1 = c(1,2,3))
print(is.data.table(m))
m[,sum(c1)]
}
如果我将此功能复制并粘贴到R中,此功能正常工作:
> foo <- function() {
+ m <- data.table(c1 = c(1,2,3))
+ print(is.data.table(m))
+ m[,sum(c1)]
+ }
> foo()
[1] TRUE
[1] 6
但是,如果我只是加载导出的函数,R认为data.table是一个data.frame并且中断:
> rm(foo)
> load_all()
Loading test_package
> foo
function() {
m <- data.table(c1 = c(1,2,3))
print(is.data.table(m))
m[,sum(c1)]
}
<environment: namespace:test_package>
> foo()
[1] TRUE
Error in `[.data.frame`(x, i, j) : object 'c1' not found
什么了?
更新
感谢@GSee的帮助。看起来这实际上是一个devtools问题。查看下面的交互式命令行代码。
加载test_package库后,foo
正确运行:
> foo
function ()
{
m <- data.table(c1 = c(1, 2, 3))
print(is.data.table(m))
m[, sum(c1)]
}
<environment: namespace:test_package>
> foo()
[1] TRUE
[1] 6
运行load_all()
会打破foo:
> load_all()
Loading test_package
> foo()
[1] TRUE
Error in `[.data.frame`(x, i, j) : object 'c1' not found
以某种方式source('R/foo.R')
恢复foo功能:
> source('R/foo.R')
> foo
function() {
m <- data.table(c1 = c(1,2,3))
print(is.data.table(m))
m[,sum(c1)]
}
> foo()
[1] TRUE
[1] 6
以后拨打load_all()
的电话不会再次中断foo
:
> load_all()
Loading test_package
> foo
function() {
m <- data.table(c1 = c(1,2,3))
print(is.data.table(m))
m[,sum(c1)]
}
> foo()
[1] TRUE
[1] 6
此外,我更新了devtools 1.5并尝试添加.datatable.aware=TRUE
,但这似乎没有做任何事情。
答案 0 :(得分:12)
正如@GSee指出的那样(在评论下)似乎仍然是this issue。
为了确定某个包是否 data.table aware ,data.table
调用函数cedta()
,即:
> data.table:::cedta
function (n = 2L)
{
te = topenv(parent.frame(n))
if (!isNamespace(te))
return(TRUE)
nsname = getNamespaceName(te)
ans = nsname == "data.table" || "data.table" %chin% names(getNamespaceImports(te)) ||
"data.table" %chin% tryCatch(get(".Depends", paste("package",
nsname, sep = ":"), inherits = FALSE), error = function(e) NULL) ||
(nsname == "utils" && exists("debugger.look", parent.frame(n +
1L))) || nsname %chin% cedta.override || identical(TRUE,
tryCatch(get(".datatable.aware", asNamespace(nsname),
inherits = FALSE), error = function(e) NULL))
if (!ans && getOption("datatable.verbose"))
cat("cedta decided '", nsname, "' wasn't data.table aware\n",
sep = "")
ans
}
<bytecode: 0x7ff67b9ca190>
<environment: namespace:data.table>
此处的相关检查是:
"data.table" %chin% get(".Depends", paste("package", nsname, sep=":"), inherits=FALSE)
如果依赖于 <{1}},上述命令应该返回data.table
- 也就是说,如果您通过TRUE
安装了软件包,然后加载了包。这是因为,当您加载包时,R默认情况下也会在命名空间中创建一个“.Depends”变量。如果你这样做了:
R CMD INSTALL
但是,当你执行ls("package:test", all=TRUE)
# [1] ".Depends" "foo"
时,似乎没有设置此变量。
devtools:::load_all()
所以,# new session + set path to package's dir
devtools:::load_all()
ls("package:test", all=TRUE)
# [1] "foo"
并不知道这个包确实依赖 cedta()
。但是,当您手动设置data.table
时,行:
.datatable.aware=TRUE
执行,返回TRUE,从而克服了问题。但是identical(TRUE, get(".datatable.aware", asNamespace(nsname), inherits = FALSE))
没有将devtools
变量放在包的命名空间中的事实仍然存在。
总而言之,.Depends
确实存在 问题。