【发布时间】:2019-12-06 05:06:48
【问题描述】:
在对 data.table 中的列进行分组修改时,我遇到了一些意外行为:
# creating a data.frame
data <- data.frame(sequence = rep(c("A","B","C","D"), c(2,3,3,2)), trim = 0, random_value = NA)
data[c(1:4, 10), "trim"] <- 1
# copying data to data_temp
data_temp <- data
# assigning some random value to data_temp so that it should no longer be a
# copy of "data"
data_temp[1, "random_value"] <- rnorm(1)
# converting data_temp to data.table
setDT(data_temp)
# expanding trim parameter to group and subsetting
data_temp <- data_temp[, trim := sum(trim), by = sequence][trim == 0]
data_temp 按预期出现,只剩下“C”序列条目。但是,我也希望“数据”对象保持不变。不是这种情况。 “数据”对象如下所示:
sequence trim random_value
1 A 2 NA
2 A 2 NA
3 B 2 NA
4 B 2 NA
5 B 2 NA
6 C 0 NA
7 C 0 NA
8 C 0 NA
9 D 1 NA
10 D 1 NA
所以“trim”变量的引用赋值也发生在原始data.frame中。
出于兼容性原因,我正在使用 data.table_1.11.4 和 R 版本 3.4.3。
错误是使用旧版本导致的还是我做错了什么/我是否需要更改代码以避免该错误?
【问题讨论】:
-
阅读
help("copy")。 -
啊,谢谢。很高兴知道,如果我复制的对象实际上不是 data.table 对象而是 data.frames,也有必要使用 copy(),其中只有一个稍后会成为 data.table。
-
@Roland 我很惊讶地看到
data_temp[1, "random_value"] <- rnorm(1)没有复制整个data.frame,而只是复制了“random_value”向量。因此,在这一行之后,单独的 data.frames 的 sequence 和 trim 变量仍然指向内存中的相同对象。我用.Internal(inspect(.))验证了这一点。我想知道这种行为在基础 R 中的默认行为有多长时间了。也许是因为允许列表保存指针? -
@大卫。目前还不清楚这是一个重复的问题。尽管“在做任何事情之前创建副本”的建议可以解决这两个问题,但
->的复制行为对于 data.frame 和 data.table 对象是不同的。您可以通过使用 data.framea 重复 matt dowle 的示例并检查向量的内存位置来看到这一点。这将更准确地反映上述情况。
标签: r data.table