R data.table中断导出的函数 [英] R data.table breaks in exported functions

查看:158
本文介绍了R data.table中断导出的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,让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 break foo 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 function cedta(), 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 return TRUE - that is, if you installed the package via R 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 on data.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆