2012-06-14 1 views
23

Ho un data.frame in R con 19 milioni di righe e 90 colonne. Ho un sacco di RAM di ricambio e cicli della CPU. Sembra che la modifica di un singolo nome di colonna in questo frame di dati sia un'operazione molto intensa per R.Perché la modifica di un nome di colonna richiede molto tempo con un data.frame di grandi dimensioni?

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

Perché è così? In qualche modo, ogni riga memorizza il nome della colonna? Sta creando un frame di dati completamente nuovo? Sembra che questa operazione dovrebbe essere completata in un tempo trascurabile. Non vedo nulla di ovvio nello R manual entry.

Sto eseguendo la build 7600 di R (64 bit) su Windows 7 e nel mio attuale spazio di lavoro, l'impostazione di nomi su un piccolo data.frame richiede "0" in base a system.time().

Modifica: sono a conoscenza della possibilità di utilizzare data.table e, onestamente, posso attendere 5 minuti per il completamento della rinomina mentre vado a prendere un tè. Quello che mi interessa è cosa sta succedendo e perché?

+0

Stranamente, stavo proprio leggendo su questo. Credo che in realtà possa copiare il df _twice_. Se utilizzi la versione 2.15.0, prova a installare e caricare il pacchetto ** dataframe ** e verifica se questo è di aiuto. – joran

+5

Matthew Dowle lo spiega molto bene [qui] (http://stackoverflow.com/questions/10655438/rename-one-named-column-in-r/10655997#10655997) e fornisce una soluzione con il pacchetto 'data.table' . – Chase

+0

Grazie, uso già 'data.table' un bel po '(e sono in debito con Matthew Dowle per avermi tirato fuori da situazioni appiccicose!) - eccomi dopo una spiegazione di cosa sta succedendo ... e idealmente perché. La risposta è davvero "data.frame è mal codificata"? – Ina

risposta

21

Poiché diversi commentatori hanno già detto, rinomina colonne frame di dati è lenta, perché (a seconda di come si fa) rende tra 1 e 4 copie dell'intero data.frame. Qui, da data.table 's pagina di aiuto ?setkey, è il modo più bello di dimostrare questo comportamento che ho visto:

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? 

A (inizio) capire il motivo per cui le cose sono fatte in questo modo, avrete probabilmente bisogno approfondire alcune delle discussioni relative a R-Devel. Qui ci sono un paio: R-devel: speeding up perception e R-devel: Confused about NAMES

La mia lettura impressionistica di quei fili è che:

  1. Almeno una copia è fatto in modo che le modifiche ad esso possono essere 'sperimentate' prima di sovrascrivere l'originale. Quindi, se qualcosa non va nel valore da riassegnare, [<-.data.frame o names<- possono "tornare indietro" e consegnare un messaggio di errore senza aver arrecato alcun danno all'oggetto originale.

  2. Diversi membri di R-core non sono completamente soddisfatti di come stanno andando le cose al momento. Diverse persone spiegano che in alcuni casi "R perde traccia"; Luke Tierney indica di aver provato alcune modifiche relative a questa copia in passato "in alcuni casi e ha sempre dovuto fare marcia indietro"; e Simon Urbanek suggerisce che "ci possono essere alcune cose che si avvicina, anche"

(Come ho detto, però, che è solo impressionistico: io non sono semplicemente in grado di seguire una conversazione completo circa i dettagli di R interni)


anche rilevanti, nel caso in cui non avete visto, ecco come fare qualcosa di simile names(z)[3] <- "c2" "realmente" funziona:!

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

Nota: Gran parte di questa risposta proviene dalla risposta di Matthew Dowle allo this other question. (Ho pensato che valesse la pena inserirlo qui, dandogli un po 'più di esposizione, dal momento che è così rilevante per la tua stessa domanda).

+1

++ per analizzare i thread di R-devel, stavo attraversando un periodo difficile a girare quelle conversazioni. – Ina