我在理解传递的引用属性方面遇到了一些麻烦data.table.有些操作似乎"打破"了参考,我想准确理解发生了什么.
在data.table从另一个创建a 时data.table(通过<-,然后更新新表:=,原始表也会被更改.这是预期的,按照:
?data.table::copy
和stackoverflow:传递引用操作在数据表包中
这是一个例子:
library(data.table)
DT <- data.table(a=c(1,2), b=c(11,12))
print(DT)
# a b
# [1,] 1 11
# [2,] 2 12
newDT <- DT # reference, not copy
newDT[1, a := 100] # modify new DT
print(DT) # DT is modified too.
# a b
# [1,] 100 11
# [2,] 2 12
Run Code Online (Sandbox Code Playgroud)
但是,如果我:=在<-赋值和:=上面的行之间插入非基础修改,DT现在不再修改:
DT = data.table(a=c(1,2), b=c(11,12))
newDT …Run Code Online (Sandbox Code Playgroud) 我正在编写一个函数,除其他外,将输入强制转换为data.table.
library(data.table)
df <- data.frame(id = 1:10)
f <- function(df){setDT(df)}
f(df)
df[, temp := 1]
Run Code Online (Sandbox Code Playgroud)
但是,最后一个命令输出以下警告:
警告消息:在
[.data.table(DF,:=(温度,1)):检测到并通过取整个表的副本固定无效.internal.selfref使得:=可以通过参考添加此新列.在较早的时候,此data.table已被R复制(或使用structure()或类似方法手动创建).避免使用键< - ,名称< - 和attr < - 当前(并且奇怪地)在R中可以复制整个data.table.使用set*语法来避免复制:?set,?setnames和?setattr.另外,在R <= v3.0.2中,列表(DT1,DT2)复制了整个DT1和DT2(用于复制命名对象的R列表()); 如果是咬人,请升级到R> v3.0.2.如果此消息没有帮助,请向datatable-help报告,以便修复根本原因.
我正在使用data.table和R 3.1.1的v1.9.3.这是否意味着df在某些时候复制?如何避免这种警告?
编辑:setDT实际使用NSE 的代码.所以这似乎有效:
df1 <- data.frame(id = 1:10)
f <- function(df){eval(substitute(setDT(df)),parent.frame())}
f(df1)
df1[, temp := 1]
Run Code Online (Sandbox Code Playgroud)
看来我可以做其他的东西在函数内DF f像
df1 <- data.frame(id = 1:10)
f <- function(df){
eval(substitute(setDT(df)),parent.frame())
df[, temp := 1]
}
f(df1)
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
我的小组使用data.table编写了大量代码,我们偶尔会被'检测到无效的.internal.selfref并通过获取整个表的副本来修复...'警告.当通过引用函数传递数据表时,此行为可能会破坏我们的代码,我试图弄清楚如何解决它.
假设我有一个函数,它将一个列添加到data.table作为副作用 - 请注意,不返回原始的data.table.
foo <- function(mydt){
mydt[, c := c("a", "b")]
return(123)
)
> x<- data.table(a=c(1,2), b=c(3,4))
> foo(x)
[1] 123
> x
a b c
1: 1 3 a
2: 2 4 b
Run Code Online (Sandbox Code Playgroud)
x已使用新列更新.这是期望的行为.
现在假设发生的事情破坏了x中的内部自我引用:
> x<- data.table(a=c(1,2), b=c(3,4))
> x[["a"]] <- c(7,8)
> foo(x)
[1] 123
Warning message:
In `[.data.table`(mydt, , `:=`(c, c("a", "b"))) :
Invalid .internal.selfref detected and fixed by taking a copy ...
> x
a b
1: 7 3
2: 8 4
Run Code Online (Sandbox Code Playgroud)
我明白发生了什么(大部分).[["a"]]结构不是data.table友好; x被转换为数据框,然后返回到数据表,这在某种程度上搞砸了内部工作.然后在foo()内部,在添加列的引用操作期间,检测到该问题,并且制作了mydt的副本; …