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

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

问题描述

我在让 data.table 在 roxygen2 导出函数中工作时遇到问题.

I'm having a problem getting data.table to work in roxygen2 exported functions.

这是一个名为 foo.R(位于我的包的 R 目录中)的文件中的一个简单的假函数,它使用 data.table:

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)]
}

如果我将此函数复制并粘贴到 R 中,则此函数可以正常工作:

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

但如果我只是加载导出的函数,R 认为 data.table 是一个 data.frame 并中断:

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

怎么了?

更新

感谢@GSee 的帮助.看起来这实际上是一个 devtools 问题.查看下面的交互式命令行代码.

Thanks to @GSee for the help. Looks like this is actually a devtools issue. Check out the interactive command line code below.

加载test_package库后,foo正常运行:

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

运行 load_all() 会破坏 foo:

Running load_all() breaks 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 功能:

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

以后对 load_all() 的调用不会再次破坏 foo:

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

另外,我更新到 devtools 1.5 并尝试添加 .datatable.aware=TRUE,但这似乎没有任何作用.

Also, I updated to devtools 1.5 and tried adding .datatable.aware=TRUE, but that didn't seem to do anything.

推荐答案

正如@GSee 指出的(在评论下),问题似乎是 这个问题仍然存在.

The issue, as @GSee pointed out (under comments) seems to be this issue still.

为了判断一个包是否支持data.tabledata.table调用函数cedta(),即:

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
", 
            sep = "")
    ans
}
<bytecode: 0x7ff67b9ca190>
<environment: namespace:data.table>

这里的相关检查是:

"data.table" %chin% get(".Depends", paste("package", nsname, sep=":"), inherits=FALSE)

当一个包depends依赖于data.table,上面的命令应该返回TRUE——也就是说,如果你通过R CMD INSTALL 然后加载包.这是因为,当您加载包时,R 默认情况下也会在命名空间中创建一个.Depends"变量.如果你这样做了:

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"     

但是,当您执行 devtools:::load_all() 时,似乎没有设置此变量.

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"

所以,cedta() 并不知道这个包确实依赖 data.table.但是,当您手动设置 .datatable.aware=TRUE 时,该行:

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))

被执行,这将返回 TRUE,从而解决了这个问题.但是 devtools 没有将 .Depends 变量放在包的命名空间中的事实仍然存在.

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.

总而言之,这真的不是 data.table 的问题.

All in all, this is really not an issue with data.table.

这篇关于R data.table 在导出的函数中中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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