任何人都可以向我解释为什么bar不起作用?这是一个错误data.table吗?
Circles<-data.table(radius=1:10)
foo<-function(Circ){
Circ[,diameter:=2*radius]
}
dput(x = foo,file = 'func.R')
bar<-dget(file = 'func.R')
foo(Circles)
bar(Circles)
Run Code Online (Sandbox Code Playgroud)
它与dget函数设置它返回的对象的环境这一事实有关.GlobalEnv.有一个简单易用的工作,但它会让像我这样的新手疯狂地试图弄清楚它为什么会破坏它.
MyDGet<-function(file){
temp<-dget(file=file)
environment(temp)<-.GlobalEnv
return(temp)
}
bar<-MyDGet(file = 'func.R')
Run Code Online (Sandbox Code Playgroud)
来自dput:
如果x是函数,则剥离关联的环境.因此,范围信息可能会丢失.
parent.env(environment(bar))
# <environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
双方foo(Circles)并bar(Circles)导致[.data.table越来越出动,但在的情况下bar(),看着traceback():
traceback()
# 6: stop("Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(\":=\").")
# 5: `:=`(diameter, 2 * radius)
# 4: `[.data.frame`(x, i, j)
# 3: `[.data.table`(Circ, , `:=`(diameter, 2 * radius)) at func.R#3
# 2: Circ[, `:=`(diameter, 2 * radius)] at func.R#3
# 1: bar(Circles)
Run Code Online (Sandbox Code Playgroud)
正如你所看到[.data.table分派给[.data.frame.发生这种情况的原因在于[.data.table:
if (!cedta()) {
# Fix for #5070 (to do)
Nargs = nargs() - (!missing(drop))
ans = if (Nargs<3L) `[.data.frame`(x,i) # drop ignored anyway by DF[i]
else if (missing(drop)) `[.data.frame`(x,i,j)
else `[.data.frame`(x,i,j,drop)
# added is.data.table(ans) check to fix bug #5069
if (!missing(i) & is.data.table(ans)) setkey(ans,NULL) # See test 304
return(ans)
}
Run Code Online (Sandbox Code Playgroud)
这!cedta()是以下TRUE情况bar().我们可以cedta通过设置options(datatable.verbose=TRUE)和重新运行来确认这是一个问题.然后我们得到:
# cedta decided 'base' wasn't data.table aware
Run Code Online (Sandbox Code Playgroud)
那怎么cedta()办?
假设您正在使用data.table对象,并且还使用不了解data.table数据结构的包.让我们说这个包有一个叫做的函数funA.你正在调用函数如下:
funA(DT)
Run Code Online (Sandbox Code Playgroud)
现在由于包不是data.table,它可能使用如下代码:
funA <- function(...) {
....
tmp <- DT[, cols]
....
}
Run Code Online (Sandbox Code Playgroud)
这里DT[, cols]不会对data.table正确由于data.table的默认设置一些细微的差别(默认工作with = TRUE).对于data.table,我们需要DT[, cols, with=FALSE].
为了使您的代码能够正常工作,我们必须确定您在一个函数中使用data.table对象,该函数不知道如何从data.table(或者换句话说,不是数据)中对列进行子集化.table意识到).
我们通过查看函数的父环境并提供您正在使用的包的命名空间(如果您正在使用包),然后检查此包是否导入或依赖于data.table来实现. ,或者它是我们列入白名单的其中一个软件包.
这种情况很特殊(或奇怪),因为您定义的函数具有父环境base,并且命名空间base不是data.table.
因此,这实际上不是一个错误.
?dget将此描述为不是在R会话之间传输对象的好方法(在NOTE部分下).saveRDS工作正常,您可以使用它作为替代(更好)的解决方法:
saveRDS(foo, "func.RDS")
bar <-readRDS("func.RDS")
bar(Circles) # works
Run Code Online (Sandbox Code Playgroud)