2015-05-14 29 views
5

Ho 2 file csv con gli stessi nomi di colonna, ma valori diversi.panda: concatenate dataframes, forward-fill e multiindex su dati colonna

La prima colonna è l'indice (time) e una delle colonne di dati è un identificatore univoco (id)

L'indice (time) è diverso per ogni file csv.

Ho letto i dati in 2 dataframes utilizzando read_csv, dandomi il seguente:

 +-------+------+-------+ 
     | id | size | price | 
+-------+-------+------+-------+ 
| time |  |  |  | 
+-------+-------+------+-------+ 
| t0 | ID1 | 10 | 110 | 
| t2 | ID1 | 12 | 109 | 
| t6 | ID1 | 20 | 108 | 
+-------+-------+------+-------+ 

     +-------+------+-------+ 
     | id | size | price | 
+-------+-------+------+-------+ 
| time |  |  |  | 
+-------+-------+------+-------+ 
| t1 | ID2 | 9 | 97 | 
| t3 | ID2 | 15 | 94 | 
| t5 | ID2 | 13 | 100 | 
+-------+-------+------+-------+ 

vorrei creare un unico grande dataframe con voci per entrambi, e utilizzare ffill per inoltrare compilare valori dal passo temporale precedente.

Sono in grado di ottenere ciò utilizzando una combinazione di concat, sort e ffill.

Tuttavia, esso richiede rinominare le colonne di uno dei dataframes prima, in modo che non ci sono il nome scontri

df2.columns = [ 'id', 'id2_size', 'id2_price' ] 
df = pd.concat([df1, df2]).sort().ffill() 

Ciò comporta i seguenti dataframe:

 +------+------+-------+----------+-----------+ 
     | id | size | price | id2_size | id2_price | 
+-------+------+------+-------+----------+-----------+ 
| time |  |  |  |   |   | 
+-------+------+------+-------+----------+-----------+ 
| t0 | ID1 | 10 | 110 |  nan |  nan | 
| t1 | ID2 | 10 | 110 |  9 |  97 | 
| t2 | ID1 | 12 | 109 |  9 |  97 | 
| t3 | ID2 | 12 | 109 |  15 |  94 | 
| t5 | ID2 | 12 | 109 |  13 |  100 | 
| t6 | ID1 | 20 | 108 |  13 |  100 | 
+-------+------+------+-------+----------+-----------+ 

mio metodo attuale è abbastanza klunky in quanto devo rinominare le colonne di uno dei dataframes.

Credo che un modo migliore per rappresentare i dati sarebbe utilizzare uno multiindex con il valore della seconda dimensione proveniente dalla colonna id.

Il dataframe risultante sarebbe simile a questa:

 +--------------+--------------+ 
     | ID1   | ID2   | 
     +------+-------+------+-------+ 
     | size | price | size | price | 
+-------+------+-------+------+-------+ 
| time |  |  |  |  | 
+-------+------+-------+------+-------+ 
| t0 | 10 | 110 | nan | nan | 
| t1 | 10 | 110 | 9 | 97 | 
| t2 | 12 | 109 | 9 | 97 | 
| t3 | 12 | 109 | 15 | 94 | 
| t5 | 12 | 109 | 13 | 100 | 
| t6 | 20 | 108 | 13 | 100 | 
+-------+------+-------+------+-------+ 

è possibile?
In tal caso, quali passaggi sarebbero necessari per passare dai 2 frame di dati letti da csv al dataframe finale multiindexed unito?

risposta

1

Ecco una battuta che fa quello che si chiede, anche se è un po 'contorto, in termini di accatastamento/unstacking:

df1.append(df2).set_index(['time','id']).sort().stack().unstack(level=[1,2]).ffill() 

id ID1  ID2  
    size price size price 
time      
t0  10 110 NaN NaN 
t1  10 110 9 97 
t2  12 109 9 97 
t3  12 109 15 94 
t5  12 109 13 100 
t6  20 108 13 100 

FWIW, il mio approccio di default sarebbe stato qualcosa di simile a quanto segue, che è un po 'più semplice (meno impilamento/unstacking) e darebbe gli stessi risultati di base, ma con una diversa organizzazione della colonna:

df1.append(df2).set_index(['time','id']).sort().unstack().ffill() 

    size  price  
id ID1 ID2 ID1 ID2 
time      
t0  10 NaN 110 NaN 
t1  10 9 110 97 
t2  12 9 109 97 
t3  12 15 109 94 
t5  12 13 109 100 
t6  20 13 108 100 

e in questo senso, si potrebbe quindi aggiungere swaplevel e sort per ottenere le colonne r eorganized essere come nel primo approccio:

df1.append(df2).set_index(['time','id']).sort().unstack().ffill().swaplevel(0,1,axis=1).sort(axis=1) 
+0

df1.append (DF2) .set_index '([ 'tempo', 'id'])' 'fallisce con KeyError: u'no elemento denominato time''. Penso che sia perché 'time' è l'indice e' set_index' guarda le intestazioni delle colonne. Come dovrei specificare di usare il 'tempo' dell'indice esistente e includere anche la colonna' id'? –

+0

Il trucco è usare 'append' che aggiunge una colonna all'indice esistente. 'df1.append (fd2) .set_index ('id', append = True)' –

+0

OK sembra che tu l'abbia capito. Ho iniziato con il default [0,1,2, ...] indici in ognuno - quindi 'time' e' id' erano solo colonne regolari. Si potrebbe arrivare a questo tramite 'reset_index()' o semplicemente fare quello che hai fatto, ovviamente. Di solito precedo 'set_index' con' reset_index' in quei casi solo per iniziare con una lavagna vuota per l'indice. – JohnE

Problemi correlati