为什么更改列名需要花费很长时间才能使用大型data.frame?

Ina*_*Ina 23 r dataframe data.table

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

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

为什么会这样?每行都以某种方式存储列名吗?这会创建一个全新的数据框吗?看来这个操作应该在微不足道的时间内完成.我在R手册中没有看到任何明显的东西.

我正在Windows 7上运行构建7600的R(64位),在我当前的工作区中,在一个小数据上设置colnames.frame需要'0'时间system.time().

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

Jos*_*ien 21

正如一些评论者提到的那样,重命名数据框列的速度很慢,因为(取决于你如何做),它会产生1到4个整个data.frame的副本.这里,从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?
Run Code Online (Sandbox Code Playgroud)

为了(开始)理解为什么事情以这种方式完成,你可能需要深入研究一些关于R-devel的相关讨论.以下是一对:R-devel:加速感知R-devel:对NAMES感到困惑

我对这些主题的印象主义解读是:

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

  2. R-core的几个成员对现在的工作方式并不完全满意.有几个人解释说在某些情况下"R失去了轨道"; Luke Tierney表示他过去曾尝试过一些与此复制有关的修改"在少数情况下并且总是不得不退缩"; 和Simon Urbanek暗示"也许会有一些事情发生"

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


同样相关,万一你没有看到它,这里是names(z)[3] <- "c2""真正"的工作方式:

# From ?names<-
z <- "names<-"(z, "[<-"(names(z), 3, "c2"))
Run Code Online (Sandbox Code Playgroud)

注意:大部分答案来自马修道尔对这个问题的回答.(我认为值得把它放在这里,给它更多曝光,因为它与你自己的问题非常相关).