我正在尝试找出我在下面的代码中遇到的data.table'invalid .selfref'错误。
library(data.table)
library(dplyr)
DT <- data.table(aa=1:100, bb=rnorm(n=100), dd=gl(2,100))
DT <- DT %.% group_by(dd, aa) %.% summarize(m=mean(bb))
DT <- DT[, ee := 3]
Run Code Online (Sandbox Code Playgroud)
最后一行引发错误。这里有一个建议,就是将最后一行写为,DT$ee <- 3但并不能真正解释它为什么起作用(和:=不能起作用),并且作为一个初学者data.table用户也不觉得自己是正确的data.table习惯用法。
它与那里的dplyr线有关,显然改变了DT数据表。但是,当我将该行(及其后面的行)更改为该行时,DDT <- DT %.% group_by() ...仍然会从该DT[, ee := 3]行收到selfref错误。
一直在检查各种来源,但那里的所有信息并没有真正减少,因此我仍然感到困惑。
R version 3.1.0 (2014-04-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=Dutch_Netherlands.1252 LC_CTYPE=Dutch_Netherlands.1252
[3] LC_MONETARY=Dutch_Netherlands.1252 LC_NUMERIC=C
[5] LC_TIME=Dutch_Netherlands.1252
attached base packages:
[1] graphics grDevices utils datasets stats methods base
other attached packages:
[1] dplyr_0.2 data.table_1.9.2 ggplot2_1.0.0
loaded via a namespace (and not attached):
[1] assertthat_0.1 colorspace_1.2-4 digest_0.6.4 grid_3.1.0
[5] gtable_0.1.2 MASS_7.3-31 munsell_0.4.2 parallel_3.1.0
[9] plyr_1.8.1 proto_0.3-10 Rcpp_0.11.2 reshape2_1.4
[13] scales_0.2.4 stringr_0.6.2 tools_3.1.0
Run Code Online (Sandbox Code Playgroud)
我只运行了您的代码,然后看到了问题。data.table过度分配列指针的向量(以便稍后通过引用有效地添加列),并且当操作(很可能无意间)删除了该过度分配时,会出现此警告。
让我尝试使用Matt的useR 2014演示文稿中的幻灯片45来解释过度分配。顶部的(蓝色和黄色)框对应于列指针的向量,箭头显示每个指针指向的数据。
左图以图形方式描绘了如何向作品添加(或添加cbind)一列data.frame。cbind对列进行基本上会导致(较深或较浅的)副本,从而为列指针的向量(以黄色显示)和数据(现在又有一个列)提供了新的位置。
右图显示了创建data.table方式,由于data.table创建时过度分配,开始时会有3个以上的蓝色框。通过使用:=,甚至没有进行浅拷贝。留在原处的列指针向量和下一个未使用的过度分配框用于分配新列。
这是关于区别以及这里的过度分配的含义。
现在,警告提示您所做的任何操作均已消除了此过度分配的情况 -这意味着多余的蓝色框已消失!因此,我们无法再通过引用添加列,直到我们再次过度分配 (这是不必要的,应避免使用,但由于它已经消失了,我们将做下一件最好的事情)。
我的猜测是,您的dplyr语法会以某种方式消除这种过度分配,当您使用该语法时,它会在下一步中捕获,:=并data.table在通过引用添加新列之前再次过度分配(这将导致浅表复制)。
如果我这样做data.table:
DT <- DT[, list(m=mean(bb)), by=list(dd,aa)]
DT[, ee := 3]
Run Code Online (Sandbox Code Playgroud)
它工作正常。
我现在没有时间研究dplyr或验证正在做什么。