data.table环境错误的功能

时间:2015-04-09 21:50:06

标签: 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)

它与dget函数将其返回的对象的环境设置为.GlobalEnv以外的其他东西这一事实有关。有一个简单易用的工作,但它会让像我这样的新手疯狂地试图弄清楚它为什么会在一开始就破坏。

MyDGet<-function(file){
  temp<-dget(file=file)
  environment(temp)<-.GlobalEnv
  return(temp)
}

bar<-MyDGet(file = 'func.R')

1 个答案:

答案 0 :(得分:9)

来自dput

  

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

parent.env(environment(bar))
# <environment: namespace:base>

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)

您可以看到[.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)
}

如果!cedta(),则TRUE bar()cedta。我们可以通过设置options(datatable.verbose=TRUE)并重新运行来确认这是# cedta decided 'base' wasn't data.table aware 问题。然后我们得到:

cedta()

那么data.table做了什么?

假设您正在使用data.table个对象,并且还使用了一个不了解funA数据结构的软件包。并且让我们说这个包有一个名为funA(DT) 的函数。你按照以下方式调用该函数:

funA <- function(...) {
    ....
    tmp <- DT[, cols]
    ....
}

现在由于软件包不是 data.table aware ,它可能使用如下代码:

DT[, cols]

由于data.table的默认值(默认情况下为with = TRUE)存在一些细微差别,因此DT[, cols, with=FALSE]无法正确处理data.table。对于data.table,我们需要base

为了使您的代码能够正常运行,我们必须确定您在一个函数中使用data.table对象,该函数不知道如何从数据中对列进行子集化。表(或换句话说,不是 data.table aware )。

我们通过查看函数的父环境来实现这一点,并提供您正在使用的包的命名空间(如果您正在使用包),然后我们检查此包< em> imports 或依赖在data.table上,或者如果它是我们列入白名单的其中一个软件包。

这种情况很特殊(或奇怪),因为您定义的函数的父环境为base,而命名空间?dget不是数据。

因此,这实际上并不是一个错误。

NOTE将此描述为是在R会话之间传输对象的好方法(在saveRDS部分下)。 saveRDS(foo, "func.RDS") bar <-readRDS("func.RDS") bar(Circles) # works 运行正常,您可以将其用作替代(更好)的解决方法:

{{1}}