【发布时间】:2013-02-18 04:00:30
【问题描述】:
我正在创建一个包,该包使用data.table 作为数据集,并具有几个使用:= 通过引用分配的函数。
我已经构建了一个简单的包来演示我的problem
library(devtools)
install_github('foo','mnel')
它包含两个功能
foo <- function(x){
x[, a := 1]
}
fooCall <- function(x){
eval(substitute(x[, a :=1]),parent.frame(1))
}
和一个数据集(非延迟加载)DT,使用
DT <- data.table(b = 1:5)
save(DT, file = 'data/DT.rda')
当我安装这个包时,我的理解是foo(DT) 应该在DT 中通过引用分配。
library(foo)
data(DT)
foo(DT)
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
# However this has not assigned by reference within `DT`
DT
b
1: 1
2: 2
3: 3
4: 4
5: 5
如果我使用更多correct
tracmem(DT)
DT <- foo(DT)
# This works without copying
DT
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
untracemem(DT)
如果我在函数中使用eval 和substitute
fooCall(DT)
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
# it does assign by reference
DT
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
我应该坚持吗
-
DT <- foo(DT)或eval/substitute路由,或 - 关于
data如何加载数据集,即使不是懒惰,我是否有什么不明白的地方?
【问题讨论】:
-
从未尝试过通过引用更新包中的数据!但是,如果包中的数据被密封,难道它们不应该是只读的吗?在此处最后键入
DT并不意味着它是通过引用分配的,不是吗? DT 可能已被复制到.GlobalEnv,并且可能已被更新。 -
顺便说一句
tracememR 自己报告重复。不太可能捕获 data.table 所做的副本,例如在第一次过度分配时,因为从技术上讲这不是完美的复制,而是过度分配(尽管是浅拷贝而不是深拷贝)。 -
也许在包中的数据对象上尝试
alloc.col,看看会发生什么。 -
@MatthewDowle 我认为 data(DT) 在全局环境中创建了一个副本,延迟加载可能意味着数据集被锁定。我不是在尝试更新包中的副本,而是在示例/小插图中使用数据集。
-
我不熟悉
data(),但是是的,这听起来没有错。但是 R 正在创建它(不是 data.table),即 R 的data()命令不知道过度分配。与load()data.table 类似,直到第一个:=添加新列之前,它不会被过度分配。library(foo); data(DT); alloc.col(DT); foo(DT)有效吗?然后我们可以从那里开始。
标签: r data.table