2016-04-26 43 views
7

Ho una vasta lista di data.frames che devono essere legati a coppie per colonne e poi per righe prima di essere inseriti in un modello predittivo. Dato che nessun valore sarà modificato, mi piacerebbe avere il data.frame finale che punta ai data.frames originali nella mia lista.Bind data.frames per riga in R senza creare copie

Ad esempio:

library(pryr) 

#individual dataframes 
df1 <- data.frame(a=1:1e6+0, b=1:1e6+1) 
df2 <- data.frame(a=1:1e6+2, b=1:1e6+3) 
df3 <- data.frame(a=1:1e6+4, b=1:1e6+5) 

#each occupy 16MB 
object_size(df1) # 16 MB 
object_size(df2) # 16 MB 
object_size(df3) # 16 MB 
object_size(df1, df2, df3) # 48 MB 

#will be in a named list 
dfs <- list(df1=df1, df2=df2, df3=df3) 

#putting into list doesn't create a copy 
object_size(df1, df2, df3, dfs) #48MB 

data.frame finale avrà questo orientamento (ogni coppia unica data.frames legati da colonne, allora coppie vincolati da righe):

df1, df2 
df1, df3 
df2, df3 

Sono attualmente implementando questo come tale:

#generate unique df combinations 
df_names <- names(dfs) 
pairs <- combn(df_names, 2, simplify=FALSE) 

#bind dfs by columns 
combo_dfs <- lapply(pairs, function(x) cbind(dfs[[x[1]]], dfs[[x[2]]])) 

#no copies created yet 
object_size(dfs, combo_dfs) # 48MB 

#bind dfs by rows 
combo_df <- do.call(rbind, combo_dfs) 

#now data gets copied 
object_size(combo_df) # 96 MB 
object_size(dfs, combo_df) # 144 MB 

Come evitare di copiare i miei dati ma ottenere comunque la stessa fine risultato?

+5

Non pensare che tu possa. Nelle prime manipolazioni, stavi semplicemente "spostando" oggetti R da una lista a un'altra (una colonna di un data.frame è un oggetto R di per sé). L'ultimo passo riguardava le creazioni di nuovi oggetti (le colonne di 'combo_df') che * incidentalmente * contenevano i dati di due oggetti esistenti. Una copia è necessaria Un vettore in R memorizza i suoi dati * in modo contiguo *; non è possibile creare un vettore in cui una parte dei dati punti a una regione e un'altra parte a un'altra regione. – nicola

risposta

0

Memorizzando i valori come si spera, richiederebbe R per eseguire una compressione sul frame di dati. Non credo che i frame di dati supportino la compressione.

Se la tua motivazione per voler archiviare i dati in questo modo è difficile inserirla in memoria, puoi provare lo ff package. Ciò consentirebbe di memorizzarlo in un modo più compatto sul disco. La classe ffdf sembra avere le proprietà che ti servono:

Per impostazione predefinita, la creazione di un oggetto "ffdf" NON crea nuovi file ff, ma i file esistenti vengono referenziati. Questo differisce da data.frame, che crea sempre copie degli oggetti di input, in particolare in data.frame (matrix()), in cui una matrice di input viene convertita in colonne singole. per contro, ffdf memorizzerà fisicamente una matrice di input come la stessa matrice e la mapperà virtualmente alle colonne.

Inoltre, il pacchetto ff è ottimizzato per un accesso rapido.

Nota che non ho usato questo pacchetto da solo, quindi non posso garantire che risolverà il tuo problema.