我正在尝试编写使用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...
答案 0 :(得分:0)
此问题与帖子Function on data.table environment errors中描述的问题不同。它不是一个问题,只是dget
的设计方式。但对于那些好奇的人来说,这是因为dget
将对象分配给父环境base
,而命名空间base
并不是data.table
知道的。
如果x是函数,则剥离关联的环境。因此,范围信息可能会丢失。
一种解决方法是将功能分配给全局环境:
> environment(foo) <- .GlobalEnv
但我认为这里最好的解决方案是使用saveRDS
来传输R对象,这是?dget
建议的。