2013-06-19 14 views
10

Sto usando i panda per creare un'unione outer su un set di circa ~ 1000-2000 file CSV. Ogni file CSV ha una colonna identificativa id che è condivisa tra tutti i file CSV, ma ogni file ha un insieme univoco di colonne di 3-5 colonne. Ci sono circa 20.000 uniche righe id in ogni file. Tutto ciò che voglio fare è unire questi elementi, riunendo tutte le nuove colonne e utilizzando la colonna id come indice di fusione.MemoryError su grandi si fonde con i panda in Python

lo faccio con una semplice chiamata merge:

merged_df = first_df # first csv file dataframe 
for next_filename in filenames: 
    # load up the next df 
    # ... 
    merged_df = merged_df.merge(next_df, on=["id"], how="outer") 

Il problema è che con quasi 2000 file CSV, ho un MemoryError nell'operazione merge lanciata da panda. Non sono sicuro se si tratta di una limitazione dovuta a un problema nell'operazione di unione?

Il dataframe finale avrebbe 20.000 righe e approssimativamente (2000 x 3) = 6000 colonne. Questo è grande, ma non abbastanza grande da consumare tutta la memoria sul computer che sto usando che ha oltre 20 GB di RAM. Questa dimensione è troppo per la manipolazione dei panda? Dovrei usare qualcosa come sqlite invece? C'è qualcosa che posso cambiare nell'operazione merge per farlo funzionare su questa scala?

grazie.

risposta

7

credo si otterrà una migliore performance con un concat (che agisce come un outer join):

dfs = (pd.read_csv(filename).set_index('id') for filename in filenames) 
merged_df = pd.concat(dfs, axis=1) 

Questo significa che si sta facendo solo un'operazione di unione piuttosto che uno per ogni file.

+1

Come la memoria, si dovrebbe essere in grado di usare un'espressione gen invece di list comprehension ... (non sono sicuro del funzionamento interno di 'concat') – root

+0

@root bene, il generatore può essere solo migliore penso (nel caso peggiore lo converte semplicemente in una lista) :) –

+0

@root Good spot btw ! (tbh non sapevo che concat avrebbe accettato un generatore!) –

0

Ho incontrato lo stesso errore in pyt a 32 bit utilizzando read_csv con file da 1 GB. Prova versione a 64 bit e, si spera possa risolvere problema errore di memoria

0

pd.concat sembra esaurire la memoria per i grandi dataframes così, una possibilità è quella di convertire i DFS per matrici e concat questi.

def concat_df_by_np(df1,df2): 
    """ 
    accepts two dataframes, converts each to a matrix, concats them horizontally and 
    uses the index of the first dataframe. This is not a concat by index but simply by 
    position, therefore the index of both dataframes should be the same 
    """ 
    dfout = deepcopy(pd.DataFrame(np.concatenate((df1.as_matrix(),df2.as_matrix()),axis=1), 
            index = df1.index, 
            columns = np.concatenate([df1.columns,df2.columns]))) 
    if (df1.index!=df2.index).any(): 
     #logging.warning('Indices in concat_df_by_np are not the same')      
     print ('Indices in concat_df_by_np are not the same')      


    return dfout 

Tuttavia, bisogna fare attenzione a come questa funzione non è un join ma piuttosto un accodamento orizzontale, mentre dove gli indici vengono ignorati

Problemi correlati