data.table环境错误的功能

Ada*_*dam 3 r data.table

任何人都可以向我解释为什么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)

Bro*_*ieG 9

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