2012-02-29 15 views
11

Ho un grande frame di dati che richiede circa 900 MB di RAM. Poi ho provato a modificarlo in questo modo:Memoria insufficiente durante la modifica di un grande R data.frame

dataframe[[17]][37544]=0 

Sembra che rende R utilizzando più di 3G RAM e R lamenta: (. Io sono su una macchina a 32 bit) "Errore non può allocare vettore di dimensione 3,0 Mb",

ho trovato in questo modo è meglio:

dataframe[37544, 17]=0 

ma l'impronta di R ancora raddoppiato e il comando richiede un po 'di tempo per l'esecuzione.

Da uno sfondo C/C++, sono davvero confuso da questo comportamento. Ho pensato che qualcosa come dataframe[37544, 17]=0 dovrebbe essere completato in un batter d'occhio senza costi aggiuntivi di memoria (solo una cella dovrebbe essere modificata). Cosa sta facendo R per quei comandi che ho postato? Qual è il modo giusto per modificare alcuni elementi in un frame di dati, quindi senza raddoppiare l'impronta di memoria?

Grazie mille per il vostro aiuto!

Tao

+3

(Base) R è notoriamente non spettacolare nella gestione di strutture di dati di grandi dimensioni. Ti consigliamo di esaminare una combinazione dei pacchetti ** ff **, ** bigmemory ** e ** data.table **. – joran

+3

Questo non è proprio vero: i dataframes sono notoriamente inefficienti, ma ci sono strutture molto efficienti in (base) R che dovresti usare invece se ti preoccupi dell'efficienza. –

+0

@SimonUrbanek Sì, ho detto così male. Intendevo solo esattamente quello che hai detto, che i frame di dati tendono ad essere inefficienti e che i pacchetti che ho menzionato possono spesso essere utili per le persone che si occupano di dati di grandi dimensioni. – joran

risposta

8

Look up 'copy-on-write' nel contesto delle discussioni R legate alla memoria. Non appena una parte di una struttura di dati (potenzialmente molto grande) cambia, viene eseguita una copia.

Una utile regola empirica è che se il tuo oggetto più grande è N mb/gb/... di grandi dimensioni, hai bisogno di circa 3 * N di RAM. Tale è la vita con un sistema interpretato.

Anni fa, quando dovevo gestire grandi quantità di dati su macchine con (relativamente al volume di dati) macchine a 32 bit a basso ram, ho ottenuto un buon uso dalle prime versioni del pacchetto bigmemory. Usa l'interfaccia 'pointer esterno' per mantenere grandi quantità di memoria al di fuori di R. Ciò ti risparmia non solo il fattore '3x', ma forse di più in quanto puoi farcela con la memoria non contigua (che è l'altra cosa che piace a R).

+0

Grazie mille! Ho esplorato diverse opzioni menzionate nelle risposte. Ho trovato grande memoria abbastanza facile per te e sufficiente per me. – agmao

+7

@agmao Oppure puoi provare ': =' in 'data.table' che fa esattamente quello che vuoi. –

7

I frame di dati sono la struttura peggiore a cui è possibile scegliere di apportare modifiche. A causa della complessa gestione di tutte le funzionalità (come il mantenimento dei nomi delle righe in sincronia, corrispondenza parziale, ecc.) Che avviene in puro codice R (diversamente dalla maggior parte degli altri oggetti che possono andare direttamente a C) tendono a forzare copie aggiuntive come non puoi modificarli sul posto. Controlla R-devel sulle discussioni dettagliate su questo argomento - è stato discusso più volte.

La regola pratica è di non utilizzare mai i frame di dati per i dati di grandi dimensioni, a meno che non li si tratti di sola lettura. Sarai di ordine di grandezza più efficiente se lavori su vettori o matrici.

4

C'è un tipo di oggetto chiamato ffdf nel pacchetto ff che è fondamentalmente un data.frame memorizzato su disco. Oltre agli altri suggerimenti sopra puoi provarlo.

Puoi anche provare il pacchetto RSQLite.

12

Seguendo su Joran suggerendo data.table, ecco alcuni link. Il tuo oggetto, a 900 MB, è gestibile nella RAM anche in 32 bit R, senza copie.

When should I use the := operator in data.table?

Why has data.table defined := rather than overloading <-?

Inoltre, data.table v1.8.0 (non ancora in CRAN ma stabile sul R-Forge) ha una funzione che fornisce set() assegnazione ancora più veloce di elementi, più velocemente assegnazione a matrix (appropriato per l'uso all'interno di loop per esempio). Vedi latest NEWS per ulteriori dettagli ed esempi. Vedi anche ?":=" che è collegato da ?data.table.

E, qui ci sono 12 questions su StackTranslate con il tag data.table contenente la parola "riferimento".

Per completezza:

require(data.table) 
DT = as.data.table(dataframe) 
# say column name 17 is 'Q' (i.e. LETTERS[17]) 
# then any of the following : 

DT[37544, Q:=0]    # using column name (often preferred) 

DT[37544, 17:=0, with=FALSE] # using column number 

col = "Q" 
DT[37544, col:=0, with=FALSE] # variable holding name 

col = 17 
DT[37544, col:=0, with=FALSE] # variable holding number 

set(DT,37544L,17L,0)   # using set(i,j,value) in v1.8.0 
set(DT,37544L,"Q",0) 

Ma, per favore vedi questioni legate e la documentazione del pacchetto per vedere come := è più ampio di questo semplice esempio; ad esempio, combinando := con la ricerca binaria in un join i.

Problemi correlati