2015-10-20 61 views
0

我试图编写使用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 

我已经冲刷计算器和唯一的线索,我能找到建议的功能可能会在不同的环境或父框架中寻找alpha

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

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

我看不到那个错误。也许你需要升级到包的版本1.9.6,目前在CRAN上。顺便说一下,因为'foo'修改'dt',所以你不需要像'test = foo(dt)'那样分配结果。只要做'foo(dt)',你就会发现'dt'本身已经改变了。 – Frank

+1

是你的包内功能吗?如果确实有数据。表导入NAMESPACE – jangorecki

+0

不在包内,但用'dget()'或'source()'手动加载。也许这与我的函数为什么无法访问'data.table'方法有关系? @Frank你是对的,我倾向于忘记':='改变'data.table'而不需要分配一个新的对象。 – Killerfurbies

回答

0

这个问题是在Function on data.table environment errors后描述的一个不同的味道。这不完全是一个问题,只是如何设计dget。但对于那些好奇的人来说,这是因为dget将对象分配给父环境base,并且名称空间base不是data.table

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

一种解决方法是将功能分配给全球enviornment:

> environment(foo) <- .GlobalEnv

但我觉得这里最好的解决方案是使用saveRDS转移[R对象,这是?dget建议。