r - 为什么 data.table 通过引用更新名称(DT),即使我分配给另一个变量?

标签 r data.table

我已经存储了一个 data.table 的名称作为vector :

library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))
names1 <- names(DT)

据我所知,这是一个普通的字符向量:

str(names1)
# chr [1:2] "x" "y"

class(names1)
# [1] "character"

dput(names1)
# c("x", "y")

但是,这不是普通的字符向量。这是一个神奇的字符向量!当我向我的 data.table 添加新列时,这个向量得到更新!

DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"

我知道这与 := 的方式有关按任务更新,但这对我来说仍然很神奇,正如我所料<-制作 data.table副本的名字。

我可以通过将名称包装在 c() 中来解决这个问题:

library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))

names1 <- names(DT)
names2 <- c(names(DT))
all.equal(names1, names2)
# [1] TRUE

DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"

names2
# [1] "x" "y"

我的问题有两个:

  1. 为什么不 names1 <- names(DT)创建 data.table 的副本的名字?在其他情况下,我们被明确警告 <-创建两个 data.table 的副本s 和 data.frame s.
  2. names1 <- names(DT) 之间有什么区别?和 names2 <- c(names(DT))

最佳答案

更新:现在已添加到 ?copy 的文档中在版本 1.9.3 中。来自 NEWS :

  1. Moved ?copy to it's own help page, and documented that dt_names <- copy(names(DT)) is necessary for dt_names to be not modified by reference as a result of updating DT by reference (ex: adding a new column by reference). Closes #512. Thanks to Zach for this SO question and user1971988 for this SO question.

您第一个问题的一部分让不太清楚您对<- 的真正含义。运算符(至少在 data.table 的上下文中),尤其是以下部分:在其他情况下,我们被明确警告 <- 创建 data.tables 和 data.frames 的副本。

因此,在回答您的实际问题之前,我将在这里简要介绍一下。如果是 data.table一个<- (赋值)仅不足以复制 data.table .例如:

DT <- data.table(x = 1:5, y= 6:10)
# assign DT2 to DT
DT2 <- DT # assign by reference, no copy taken.
DT2[, z := 11:15]
# DT will also have the z column

如果你想创建一个copy ,那么您必须使用 copy 明确提及它命令。

DT2 <- copy(DT) # copied content to DT2
DT2[, z := 11:15] # only DT2 is affected

来自CauchyDistributedRV,我明白你的意思是赋值names(dt) <- .这将导致警告。我将保留原样。


现在,回答您的第一个问题:看来 names1 <- names(DT)也有类似的行为。直到现在我才想到/知道这个。 .Internal(inspect(.))命令在这里非常有用:

.Internal(inspect(names1))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
#   @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
#   @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"

.Internal(inspect(names(DT)))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
#   @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
#   @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"

在这里,您看到它们指向相同的内存位置 @7fc86a851480 .即使是 truelengthnames1是 100(默认分配在 data.table 中,为此检查 ?alloc.col)。

truelength(names1)
# [1] 100

基本上,作业 names1 <- names(dt)似乎是通过引用发生的。即 names1指向与 dt 的列名称指针相同的位置。

回答你的第二个问题: 命令 c(.)似乎创建了一个副本因为没有检查连接操作导致的内容结果是否不同。也就是说,因为 c(.)操作可以更改向量的内容,它会立即导致进行“复制”而不检查内容是否被修改。

关于r - 为什么 data.table 通过引用更新名称(DT),即使我分配给另一个变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18662715/

相关文章:

r - 将字符串函数应用于图中的(所有)实验室类型标签

r - 使用which()查找某些posix时间之间的值并在没有数据时填充NA

r - 如何在R中创建 "max"虚拟变量?

r - 按组和逻辑表达式对行进行子集化 - data.table

r - 在 data.table 中使用平均值与 .SD 和 .SDcols

r - 仅当使用 data.table 的 := 连接两个表时才需要第一个实例

r - 无法在 Ubuntu 上安装 'XML' 的 'pmml' 软件包依赖项

r - 使用 get_map 获取黑白雄蕊图

r - 预期生命周期生存包 R

r - 如果第 x 行中的 A 列具有值,如何将第 B 列保留在第 x 行中