在用户定义的函数中处理data.table对象

时间:2015-10-20 16:23:11

标签: r scope data.table

我正在尝试编写使用data.table方法的函数来按引用添加和编辑列。但是,在函数内调用时,在控制台中工作的相同代码不起作用。这是一个简单的例子:

> dt <- data.table(alpha = c("a","b","c"), numeric = 1:3)
> foo <- function(x) {
    print(is.data.table(x))
    x[,"uppercase":=toupper(alpha)]
}

当我调用此函数时,出现以下错误。

> test = foo(dt)
[1] TRUE
 Error in `:=`("uppercase", toupper(alpha)) : 
 Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are
 defined for use in j, once only and in particular ways. See help(":="). 

然而,如果我直接在控制台中输入相同的代码,它的效果非常好。

> dt[,"uppercase":=toupper(alpha)]
> dt
   alpha numeric uppercase
1:     a       1         A
2:     b       2         B
3:     c       3         C

我已经搜索了stackoverflow,我能找到的唯一线索表明该函数可能在不同的环境或父框架中寻找alpha

编辑:重现错误的详细信息。该函数不在包中,而是直接在全局环境中声明。我以前没有意识到这一点,但为了重现错误,我需要将函数转储到文件,然后加载它。我已通过dput保存了我的所有个人功能,并将其加载到带有dget的R中,这就是我经常遇到此错误的原因。

> dput(foo, "foo.R")
> foo <- dget("foo.R")
> foo(dt)
 Error in `:=` etc...

1 个答案:

答案 0 :(得分:0)

此问题与帖子Function on data.table environment errors中描述的问题不同。它不是一个问题,只是dget的设计方式。但对于那些好奇的人来说,这是因为dget将对象分配给父环境base,而命名空间base并不是data.table知道的。

  

如果x是函数,则剥离关联的环境。因此,范围信息可能会丢失。

一种解决方法是将功能分配给全局环境:

> environment(foo) <- .GlobalEnv

但我认为这里最好的解决方案是使用saveRDS来传输R对象,这是?dget建议的。