R data.table中断导出的函数 [英] R data.table breaks in exported functions
问题描述
我有一个问题,让data.table在roxygen2导出的函数中工作。
这是一个简单的,假的函数在一个文件foo.R在我的包的R目录)它使用data.table:
#'Data.table测试函数
# '@export
foo< - function(){
m< - data.table(c1 = c(1,2,3))
print(is.data.table ))
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()
加载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
错误在`.data.frame`(x,i,j):object'c1'not found
是什么?
UPDATE b
感谢@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
code> load_all()分隔foo:
load_all()
加载test_package
> foo()
[1] TRUE
错误在`.data.frame`(x,i,j):object'c1'not found
不知何故 source('R / foo.R')
revives 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()
加载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
,但似乎没有做任何事情。
@GSee指出(在评论下)的问题似乎是 此问题 。
为了确定包是否为 data.table感知 , 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(依赖,粘贴(package,
nsname,sep =:),inherits = FALSE),error = function )NULL)||
(nsname ==utils&& exists(debugger.look,parent.frame(n +
1L))) nsname%chin%cedta.override || same(TRUE,
tryCatch(get(。datatable.aware,asNamespace(nsname),
inherits = FALSE),error = function(e)NULL))
if &&&&&&get; getOption(datatable.verbose))
cat(cedta decided,nsname,'not not data.table aware\,
sep =
ans
}
< bytecode:0x7ff67b9ca190>
< environment:namespace:data.table>
这里的相关检查是:
data.table%chin%get(依赖,粘贴(package,nsname,sep =:),inherits = FALSE)
当依赖 data.table
,上面的命令应该返回 TRUE
- 也就是说,如果你通过 R CMD INSTALL
包。这是因为,当您加载包时,R默认在命名空间中创建一个.Depends变量。如果你这样做:
ls(package:test,all = TRUE)
#[1]。取决于foo
但是,当你做 devtools ::: load_all ()
,此变量似乎未设置。
#new session + set path to package's dir
devtools ::: load_all()
ls(package:test,all = TRUE)
#[1]foo
所以, cedta()
不知道这个包确实 depends 在 data.table
。但是,当您手动设置 .datatable.aware = TRUE
时,行:
identical(TRUE,get(。datatable.aware,asNamespace(nsname),inherits = FALSE))
被执行,它将返回TRUE,因此克服了这个问题。但是,
devtools
不会将.Depends
变量放在包的命名空间中。
总而言之,这真的是
data.table
的问题。I'm having a problem getting data.table to work in roxygen2 exported functions.
Here's a simple, fake function in a file called foo.R (located in the R directory of my package) which uses 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)] }
If I copy and paste this function into R, this function works fine:
> foo <- function() { + m <- data.table(c1 = c(1,2,3)) + print(is.data.table(m)) + m[,sum(c1)] + } > foo() [1] TRUE [1] 6
But if I simply load the exported function, R thinks that the data.table is a data.frame and breaks:
> 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
What's up?
UPDATE
Thanks to @GSee for the help. Looks like this is actually a devtools issue. Check out the interactive command line code below.
After loading the test_package library,
foo
runs correctly:> 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
Running
load_all()
breaks foo:> load_all() Loading test_package > foo() [1] TRUE Error in `[.data.frame`(x, i, j) : object 'c1' not found
Somehow
source('R/foo.R')
revives foo functionality:> 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
And future calls to
load_all()
don't breakfoo
again:> 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
Also, I updated to devtools 1.5 and tried adding
.datatable.aware=TRUE
, but that didn't seem to do anything.解决方案The issue, as @GSee pointed out (under comments) seems to be this issue still.
In order to find out if a package is data.table aware,
data.table
calls the functioncedta()
, which is:> 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>
The relevant check here is:
"data.table" %chin% get(".Depends", paste("package", nsname, sep=":"), inherits=FALSE)
When a package depends on
data.table
, the above command should returnTRUE
- that is, if you installed the package viaR CMD INSTALL
and then loaded the package. This is because, when you load the package, R by default creates a ".Depends" variable in the namespace as well. If you did:ls("package:test", all=TRUE) # [1] ".Depends" "foo"
However, when you do
devtools:::load_all()
, this variable doesn't seem to be set.# new session + set path to package's dir devtools:::load_all() ls("package:test", all=TRUE) # [1] "foo"
So,
cedta()
doesn't get to know that this package indeed depends ondata.table
. However, when you manually set.datatable.aware=TRUE
, the line:identical(TRUE, get(".datatable.aware", asNamespace(nsname), inherits = FALSE))
gets executed, which will return TRUE and therefore overcomes the issue. But the fact that
devtools
doesn't place the.Depends
variable in the package's namespace is still there.All in all, this is really not an issue with
data.table
.这篇关于R data.table中断导出的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!