23

data.frame在 R 中有 1900 万行和 90 列。我有足够的空闲 RAM 和 CPU 周期。似乎更改此数据框中的单个列名称对于 R 来说是一项非常激烈的操作。

system.time(colnames(my.df)[1] <- "foo")
   user  system elapsed 
 356.88   16.54  373.39 

为什么会这样?每一行是否都以某种方式存储列名?这是创建一个全新的数据框吗?看来此操作应在可忽略不计的时间内完成。我在R 手册条目中没有看到任何明显的内容。

我在 Windows 7 上运行 R(64 位)的 build 7600,并且在我当前的工作区中,在一个小的 data.frame 上设置 colnames 根据system.time().

编辑:我知道使用的可能性data.table,老实说,我可以在去喝茶的同时等待 5 分钟让重命名完成。我感兴趣的是正在发生什么,为什么?

4

1 回答 1

21

正如几位评论者所提到的,重命名数据框列很慢,因为(取决于您如何操作)它会复制整个 data.frame的 1 到 4 个副本。在这里,来自data.table?setkey帮助页面,是我见过的展示这种行为的最佳方式:

DF = data.frame(a=1:2,b=3:4)       # base data.frame to demo copies
try(tracemem(DF))                  # try() for non-Windows where R is 
                                   # faster without memory profiling
colnames(DF)[1] <- "A"             # 4 copies of entire object
names(DF)[1] <- "A"                # 3 copies of entire object
names(DF) <- c("A", "b")           # 1 copy of entire object
`names<-`(DF,c("A","b"))           # 1 copy of entire object
x=`names<-`(DF,c("A","b"))         # still 1 copy (so not print method)
# What if DF is large, say 10GB in RAM. Copy 10GB just to change a column name?

要(开始)理解为什么会这样做,您可能需要深入研究 R-devel 上的一些相关讨论。这里有几个:R-devel:加速感知R-devel:对 NAMES 感到困惑

我对这些线程的印象派解读是:

  1. 至少制作一份副本,以便在覆盖原件之前可以“尝试”对其进行修改。因此,如果要重新分配的值有问题,[<-.data.frame或者names<-可以“退出”并传递错误消息,而不会对原始对象造成任何损害。

  2. R-core 的几个成员对现在的情况并不完全满意。一些人解释说,在某些情况下“R 迷失了方向”;卢克·蒂尔尼(Luke Tierney)表示,他过去“在少数情况下曾尝试过与此复制有关的一些修改,但总是不得不退缩”;西蒙厄巴内克暗示“也可能会有一些事情发生”

(不过,正如我所说,这只是印象派:我根本无法完整了解 R 的内部细节!)


同样相关的是,如果您还没有看到它,以下是names(z)[3] <- "c2"“真正”之类的工作原理:

# From ?names<-
z <- "names<-"(z, "[<-"(names(z), 3, "c2"))

注意:这个答案大部分来自 Matthew Dowle 对this other question的回答。(我认为值得将它放在这里,并给它更多的曝光,因为它与您自己的问题非常相关)。

于 2012-06-14T18:48:56.870 回答