2012-03-14 2 views
23

Ho un dataframe abbastanza grande in R che vorrei esportare in SPSS. Questo file mi ha causato ore di mal di testa cercando di importarlo in R, in primo luogo, tuttavia ho avuto successo usando read.fwf() usando le opzioni comment.char="%" (un carattere che non appare nel file) e fill= TRUE (era un file ASCII a larghezza fissa con alcune righe prive di tutte le variabili, causando messaggi di errore).Il modo più efficiente di esportare data.frames grandi (3.9 mills) in un file di testo?

In ogni caso, il mio frame di dati attualmente consiste di 3,9 mill osservazioni e 48 variabili (tutti i caratteri). Posso scriverlo in un file abbastanza rapidamente suddividendolo in 4 x 1 mill set di obs con df2 <- df[1:1000000,] seguito da write.table(df2) ecc., Ma non è possibile scrivere l'intero file in un'unica operazione senza che il computer si blocchi e necessiti di un hard reset per tornare indietro su.

Dopo aver ascoltato storie aneddotiche su come R non è adatto per dataset di grandi dimensioni per anni, questa è la prima volta che ho riscontrato un problema di questo tipo. Mi chiedo se ci sono altri approcci (basso livello di "dumping" del file direttamente su disco?) O se c'è qualche pacchetto sconosciuto che può gestire l'esportazione di file di grandi dimensioni di questo tipo in modo efficiente?

risposta

7

A occhio e croce, la tua macchina ha poca memoria RAM, quindi R sta utilizzando il file di scambio, che rallenta le cose. Se ti viene pagato per il codice, quindi l'acquisto di più RAM sarà probabilmente più economico di quello che stai scrivendo un nuovo codice.

Detto questo, ci sono alcune possibilità. È possibile esportare il file in un database e quindi utilizzare la funzionalità del database per scrivere in un file di testo. La risposta di JD Long a this question ti spiega come leggere i file in questo modo; non dovrebbe essere troppo difficile per invertire il processo. In alternativa, i pacchetti bigmemory e ff (come menzionato da Davy) potrebbero essere utilizzati per scrivere tali file.

+0

Ciao Richie, non sono sicuro se 8 GB di RAM si qualifichi come "short on RAM", anche con questo set di dati. Comunque, cercherò di usare 'sqldf()' come suggerito da JD Long poiché lo sto usando molto nelle mie analisi. Grazie per il puntatore! – jans

7

Anche se lo uso solo per leggere file molto grandi (10+ Gb), credo che il pacchetto ff abbia funzioni per scrivere dfs estremamente grandi.

+0

Ho tentato la fortuna con 'ff()', ma sono rimasto perplesso dalla sintassi utilizzata. Non riuscivo a capirlo e provarlo su sottoinsiemi del dataset originale non mi dava molto guadagni in termini di tempo. Grazie comunque. – jans

7

Bene, poiché la risposta con file molto grandi e R spesso è, è meglio scaricare questo tipo di lavoro in un database. SPSS ha connettività ODBC e il RODBC fornisce un'interfaccia da R a SQL.

Ho notato che, durante il processo di verifica delle mie informazioni, sono stato prelevato.

24

1) Se il file è costituito da tutte le stringhe di caratteri, viene salvato con write.table() molto più rapidamente se lo si cambia per la prima volta in matrix.

2) anche scriverlo in blocchi di, ad esempio 1000000 righe, ma sempre nello stesso file e utilizzando l'argomento append = TRUE.

+1

Soluzione davvero intelligente. Non funzionerà per data.frames in cui le variabili sono tipi diversi, ma sicuramente una buona soluzione qui! –

+0

hehe, dovevo fare la stessa cosa con dati di dimensioni pressoché uguali: non funzioneresti con i microdati di nascita o morte negli Stati Uniti, vero? –

+0

@tim riffe: No, ma in un certo senso, questi sono dati di nascita e parto della mucca :) – jans

13

Aggiornamento

Dopo l'intervento di Matt Dowle parallelizzazione e l'aggiunta di altri miglioramenti di efficienza, fread è ora il più 15x più veloce rispetto write.csv. Vedi la risposta collegata per maggiori informazioni.


Ora data.table ha una funzione fwrite contribuito da Otto Seiskari che sembra essere circa due volte più veloce write.csv in generale. Vedi here per alcuni parametri di riferimento.

library(data.table) 
fwrite(DF, "output.csv") 

Nota che i nomi di riga sono esclusi, in quanto il tipo data.table non fa uso di loro.