我正在编写一个函数,除其他外,它将输入强制转换为data.table。
library(data.table)
df <- data.frame(id = 1:10)
f <- function(df){setDT(df)}
f(df)
df[, temp := 1]
但是,最后一个命令输出以下警告:
警告消息:在
[.data.table
(df ,,:=
(临时,1)):无效 .internal.selfref通过获取整体的副本来检测和修复 表,以便:=可以通过引用添加此新列。在早些时候 此点,此data.table已被R复制(或已手动创建) 使用结构()或类似的)。避免键&lt; - ,名称&lt; - 和attr&lt; - 哪个 在R当前(并且奇怪地)可以复制整个data.table。使用套装* 语法而不是复制:?set,?setnames和?setattr。也, 在R&lt; = v3.0.2中,list(DT1,DT2)复制了整个DT1和DT2(R&#39; s list() 用于复制命名对象);如果是,请升级到R&gt; 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]
似乎我可以在函数f
中使用df做其他事情,如
df1 <- data.frame(id = 1:10)
f <- function(df){
eval(substitute(setDT(df)),parent.frame())
df[, temp := 1]
}
f(df1)
这是正确的方法吗?
答案 0 :(得分:16)
好问题!警告消息应该说: ...并通过采用整个表的浅副本来修复... 。将解决此问题。
setDT
做了两件事:
data.table
/ data.frame
list
alloc.col
过度分配列(以便:=
可以直接使用)如果输入不是data.table
,则第二步需要浅拷贝。这就是为什么我们将值重新分配给它的环境中的符号(setDT的父框架)。但setDT
的父框架是您的函数f()
。因此,函数中的setDT(df)
已经顺利进行,但是驻留在全局环境中的df
只会更改它的类,而不会过度分配(因为浅层副本会切断链接)。
在下一步中,:=
会再次检测到这些和浅层副本过度分配。
到目前为止,我们的想法是在提供给函数之前使用setDT
转换为data.tables 。但我希望这些案例得到解决(将会看一下)。
非常感谢!