gpt4 book ai didi

r - 关于 data.table 环境错误的函数

转载 作者:行者123 更新时间:2023-12-01 08:54:48 24 4
gpt4 key购买 nike

谁能向我解释为什么 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')

最佳答案

来自dput:

If x is a function the associated environment is stripped. Hence scoping information can be lost.

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()bar() 的情况下是 TRUE。我们可以通过设置 options(datatable.verbose=TRUE) 并重新运行来确认这是一个 cedta 问题。然后我们得到:

# cedta decided 'base' wasn't data.table aware

那么cedta()是做什么的呢?

假设您正在使用 data.table 对象,并且还使用不了解 data.table 数据结构的包。假设包有一个名为funA 的函数。你调用的函数如下:

funA(DT)

现在由于包不支持data.table,它可以使用如下代码:

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

这里 DT[, cols] 不能在 data.table 上正常工作,因为 data.table 的默认值存在一些细微差异(默认情况下 with = TRUE)。对于 data.table,我们需要 DT[, cols, with=FALSE]

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

我们通过查看函数的父环境来做到这一点,它给出了你正在使用的包的命名空间(如果你正在使用一个包),然后我们检查这个包是否 imports 取决于 data.table,或者它是否是我们列入白名单的包之一。

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

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

?dget 将其描述为 不是 在 R session 之间传输对象的好方法(在 NOTE 部分下)。 saveRDS 工作正常,您可以将其用作替代(更好的)解决方法:

saveRDS(foo, "func.RDS")
bar <-readRDS("func.RDS")
bar(Circles) # works

关于r - 关于 data.table 环境错误的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29549690/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com