【发布时间】:2015-05-17 10:25:26
【问题描述】:
我最近一直在尝试通过阅读和试验 R 中的内存使用来提高我的 R 编程技能。我最近尝试在 Hadley 的“高级 R”中重新创建一个示例,但得到了不同的结果。在this pageHadley 的底部设置如下示例:
x <- data.frame(matrix(runif(100 * 1e4), ncol = 100))
medians <- vapply(x, median, numeric(1))
然后通过展示来演示原始和非原始的区别
for(i in 1:5) {
x[, i] <- x[, i] - medians[i]
print(c(address(x), refs(x)))
}
每次循环运行时都会制作一份副本(因为 x 是一个数据框)。而
y <- as.list(x)
for(i in 1:5) {
y[[i]] <- y[[i]] - medians[i]
print(c(address(y), refs(y)))
}
就地修改 y(因为 y 已被转换为一个列表,它是一个原始对象)。但是,当我重新创建此代码时,我发现在这两个实例中都创建了副本:
> x <- data.frame(matrix(runif(100 * 1e4), ncol = 100))
> medians <- vapply(x, median, numeric(1))
>
> for(i in 1:5) {
+ x[, i] <- x[, i] - medians[i]
+ print(c(address(x), refs(x)))
+ }
[1] "0x10e4e6770" "2"
[1] "0x10e46c420" "2"
[1] "0x121110180" "2"
[1] "0x11c2c26d0" "2"
[1] "0x121151db0" "2"
> x <- data.frame(matrix(runif(100 * 1e4), ncol = 100))
> medians <- vapply(x, median, numeric(1))
> y <- as.list(x)
>
> for(i in 1:5) {
+ y[[i]] <- y[[i]] - medians[i]
+ print(c(address(y), refs(y)))
+ }
[1] "0x132aea2b0" "2"
[1] "0x1211839e0" "2"
[1] "0x11c237ea0" "2"
[1] "0x121169a80" "2"
[1] "0x10993f460" "2"
在他的示例中,Hadley 似乎至少使用了 R 3.1.0,而我使用的是 R 3.1.2(在 Mac 上)。但是,我读到的所有内容都表明,随着时间的推移,R 在内存管理方面正在变得越来越好,而上述结果表明它正在变得更糟。尽管我可能会做一些愚蠢的事情或误解一些重要的事情。谁能告诉我为什么我的复制没有像哈德利的例子一样的记忆效率?
【问题讨论】:
-
你在使用 RStudio 吗?我找到了这条注释:“请注意,如果您使用的是 RStudio,refs() 将始终返回 2:环境浏览器会引用您在命令行上创建的每个对象。”在adv-r.had.co.nz/memory.html#modification
-
我也看到了那个注释,但是:(1)我认为 Hadley 在这个例子中也在使用 RStudio,因为他是 RStudio 的首席科学家,(2)虽然 refs 可能被人为夸大了,但我不相信地址应该改变,(3)我在R中重新创建了这个例子并遇到了同样的问题。
-
击败我。在 Linux 下尝试看看这是否与操作系统有关,但得到的结果与 Win7 相同。
-
谁能解释为什么十六进制内存地址在遍历数据帧时增加,但在遍历列表时减少?
-
你得到哪个结果,我的还是 Hadley 的?
标签: r list for-loop memory dataframe