2013-02-08 19 views
5

ho creato una funzione che è chiamato a leggere e poi tornare un data.table:Trucchi per evitare la duplicazione dell'allocazione di memoria quando si restituisce data.table o data.frame in R?

read.in.data <- function(filename) 
{ 
    library(data.table) 
    data.holder<-read.table(filename, skip=1) 
    return(data.table(data.holder)) 
} 

ho notato osservando la mia RAM in quanto i processi di funzione che R sembra elaborare questo in 2 fasi (o almeno questa è la mia ipotesi migliore per quello che sta succedendo). Ad esempio, quando carico un file da 1,5 GB (15 colonne con un totale di 136 caratteri per riga), R sembra 1) leggere i dati e utilizzare 1,5 GB di RAM, quindi 2) utilizzare un altro 1,5 GB di RAM per il ritorno.

Ci sono alcuni trucchi per creare una funzione per creare un data.table (o data.frame per quella materia) e restituire data.table senza richiedere la duplicazione in memoria? O devo fare tutto il processo per data.table all'interno della funzione in cui viene creata la tabella?

Osservazioni: Se eseguo questo codice due volte di seguito, la memoria non viene cancellata; poiché ho solo 8 GB di RAM, la funzione fallisce. Se salto la fase di memorizzazione di "read.table" in una variabile (come mostrato di seguito), non ottengo alcun beneficio. Non vorrei farlo in alcun modo, dal momento che mi piacerebbe avere la possibilità di ripulire i dati.table prima di restituirlo. Una soluzione al mio problema mi permetterebbe anche di elaborare file più grandi senza esaurire la memoria.

short.read.trk <- function(fntrk) 
{ 
    library(data.table) 
    return(data.table(read.table(fntrk, skip=1))) 
} 
+4

Sento il tuo dolore. Prova a fread() in v1.8.7. Crea direttamente un data.table in modo che il wrapper data.table() di copiatura possa essere evitato, inoltre è più efficiente di read.table comunque (anche con tutti i trucchi noti applicati). –

+0

Grazie, proverò a fread() non appena 1.8.7 ha una build su r-forge (attualmente elenca come "non riuscito a creare"). – Docuemada

+0

Oops - grazie per avermelo fatto sapere - Dare un'occhiata ... –

risposta

2

Se il risparmio di memoria è per lo più quello che stai dopo, è possibile convertire uno colonna alla volta:

library(data.table) 
read.in.data <- function(filename) 
{ 
    data.holder <- read.table(filename, skip=1) 
    dt <- data.table(data.holder[[1]]) 
    names(dt) <- names(data.holder)[1] 
    data.holder[[1]] <- NULL 

    for(n in names(data.holder)) { 
    dt[, `:=`(n, data.holder[[n]]) ] 
    data.holder[[n]] <- NULL 
    } 
    return(dt) 
} 

(non testato)

Non sarà più veloce, infatti è probabilmente più lento. Ma dovrebbe essere meno dispendioso della memoria.

+0

Grazie, questo è un approccio interessante. Lo implementerò quando avrò accesso al set di dati lunedì e modificherò questo commento con i risultati. – Docuemada

+1

+1 Approccio interessante. Potrebbe essere molto veloce. Altri approcci per testare sono 'as.data.table()' piuttosto che 'data.table()' e (solo per esperti): 'setattr (data," class ", c (" data.frame "," data. tavola "))'. –

+0

+1 Mi piace l'approccio all'uso di "NULL" per mantenere bassa la memoria. Ho provato quando si collegano le tabelle insieme. Ad esempio, l'ho provato usando qualcosa come dt <-do.call ("rbind", list (dt, dt.holder)) seguito da dt.holder <-NULL. Tuttavia, l'approccio sopra riportato non ha modificato la RAM complessiva utilizzata. Confrontando il mio script originale con quello proposto, l'utilizzo della RAM era lo stesso. – Docuemada

Problemi correlati