【发布时间】:2021-09-29 18:18:45
【问题描述】:
我有一个非常简单的代码,可以在 R(和 data.table 包)中重现我的问题:
如果我将列名保存到没有 copy() 的变量中,则在代码中使用 := 运算符稍后时会覆盖它:
input_table = data.table(A = 1:3, B = 2:4)
some_value = 0.025
original_colnames <- names(input_table)
original_colnames_copy <- copy(names(input_table))
identical(original_colnames, c("A", "B")) # returns TRUE
# create a new column
input_table[, C := A + some_value]
identical(original_colnames, c("A", "B")) # returns FALSE, original_colnames contains "C" as well
identical(original_colnames_copy, c("A", "B")) # returns TRUE
如果我使用以下代码创建新列,此问题不会持续存在:
input_table = mutate(input_table, C= A + some_value)
这是有意的吗(我是否错过了 R / data.table 中的一些更深层次的知识)?
R.version 是 4.1.0,data.table 版本是 1.14.0。
【问题讨论】:
-
我相信
original_colnames是有效的(为了简单和高效)指向框架内存属性的指针,直接返回列名而不将其复制到新变量中。虽然 R 的典型值传递语义会让人相信names(.)在调用时提取名称并将它们复制到新向量中,但事实并非如此。由于data.table是通过引用工作的,它在内存中的相同属性位置添加了一个列名,因此original_colnames立即反映了差异。 -
是的,这是有意的。如果性能更差,就无法避免。
-
谢谢。我知道
data.table是通过引用工作的,但我不知道base也有类似的方法 -
我以为我已经看到了关于此的常见问题解答。有一个相关的问题 (rdatatable/data.table#3847),尽管它的链接并没有专门讨论
colnames(.)的互动。我认为 “base中的类似方式” 可能有点误导,因为分配给original_colnames对框架没有影响,如果你要使用data.frame来代替,original_colnames引用的前提仍然是相同的,但您不会看到相同的行为,因为添加列不是就地完成的(因此链接已断开)。
标签: r reference data.table