【发布时间】:2019-06-18 13:09:06
【问题描述】:
我试图更好地了解 R 中 for 循环的性能。我修改了 Hadley 的书 here 中的示例,但我仍然感到困惑。
我有以下设置,其中 for 循环遍历几个随机列:
set.seed(123)
df <- as.data.frame(matrix(runif(1e3), ncol = 10))
cols <- sample(names(df), 2)
tracemem(df)
我有一个为cols 的每个元素运行的for 循环。
for (i in seq_along(cols)) {
df[[cols[i]]] <- 3.2
}
我得到以下副本列表。
tracemem[0x1c54040 -> 0x20e1470]:
tracemem[0x20e1470 -> 0x20e17b8]: [[<-.data.frame [[<-
tracemem[0x20e17b8 -> 0x20dc4b8]: [[<-.data.frame [[<-
tracemem[0x20dc4b8 -> 0x20dc800]:
tracemem[0x20dc800 -> 0x20dc8a8]: [[<-.data.frame [[<-
tracemem[0x20dc8a8 -> 0x20dcaa0]: [[<-.data.frame [[<-
Hadley 在他的例子中指出:
其实每次迭代都不是复制一次数据框,也不是两次,而是 三次! [[.data.frame 制作了两份副本,还有一份 是因为 [[.data.frame 是一个递增的常规函数 x 的引用计数。
谁能解释一下为什么[[<-.data.frame 方法需要复制两份?
【问题讨论】:
-
我很确定原因与this 回答中讨论的相同;即你得到一个用于更改值的副本,最后从
class<-得到另一个副本,因为此时它在 NAM(2) 对象上被调用。该答案还表明,随着时间的推移,R 已经改进了一些东西,因此您可以看到浅拷贝和深拷贝,因此并非每个“拷贝”都必然会产生如此大的性能损失。