Подтвердить что ты не робот

Почему изменение имени столбца занимает очень много времени с помощью большого файла data.frame?

У меня есть data.frame в R с 19 миллионами строк и 90 столбцами. У меня много резервных циклов RAM и CPU. Кажется, что изменение одного имени столбца в этом фрейме данных является очень интенсивной операцией для R.

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

Почему это так? Каждая строка хранит имя столбца? Является ли это создание совершенно нового кадра данных? Кажется, эта операция должна завершиться в незначительное время. Я не вижу ничего очевидного в записи R.

Я запускаю сборку 7600 из R (64 бит) в Windows 7 и в моей текущей рабочей области, устанавливая имена кодов на маленьком data.frame, занимает время "0" в соответствии с system.time().

Изменить: я знаю о возможности использования data.table, и, честно говоря, я могу подождать 5 минут, чтобы переименование закончилось, пока я получаю чай. Меня интересует , что происходит и почему?

4b9b3361

Ответ 1

Как отмечалось несколькими комментаторами, переименование столбцов фрейма данных происходит медленно, потому что (в зависимости от того, как вы это делаете) оно составляет от 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: Confused on NAMES

Мое импрессионистическое чтение этих потоков таково:

  • Как минимум одна копия сделана так, чтобы ее изменения можно было "опробовать", прежде чем перезаписывать оригинал. Таким образом, если что-то не так с назначенным значением, [<-.data.frame или names<- может "отступать" и доставлять сообщение об ошибке без какого-либо ущерба исходному объекту.

  • Несколько членов R-core не полностью удовлетворены тем, как все работает сейчас. Несколько человек объясняют, что в некоторых случаях "R теряет трек"; Люк Тирни указывает, что он пробовал некоторые изменения, связанные с этим копированием в прошлом, "в нескольких случаях и всегда должен был отступать"; и Саймон Урбанек намекает, что "возможно, некоторые вещи тоже придут"

(Как я уже сказал, это просто импрессионистическое: я просто не могу полностью поговорить о деталях R-внутренних элементов!)


Также уместно, если вы его не видели, вот как работает names(z)[3] <- "c2" "действительно":

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

Примечание: Большая часть этого ответа вытекает из ответа Мэтью Доула на этот другой вопрос. (Я думал, что стоит поставить его здесь и дать ему еще больше внимания, так как он имеет отношение к вашему собственному вопросу).