2015-07-09 46 views
7

Ho un dataframe panda con due variabili id:Unmelt Pandas dataframe

df = pd.DataFrame({'id': [1,1,1,2,2,3], 
       'num': [10,10,12,13,14,15], 
       'q': ['a', 'b', 'd', 'a', 'b', 'z'], 
       'v': [2,4,6,8,10,12]}) 

    id num q v 
0 1 10 a 2 
1 1 10 b 4 
2 1 12 d 6 
3 2 13 a 8 
4 2 14 b 10 
5 3 15 z 12 

posso ruotare il tavolo con:

df.pivot('id','q','v') 

e finire con qualcosa di simile:

q a b d z 
id     
1 2 4 6 NaN 
2 8 10 NaN NaN 
3 NaN NaN NaN 12 

Tuttavia, quello che voglio veramente è (la forma originale non fusa):

id num a b d z    
1 10 2 4 NaN NaN 
1 12 NaN NaN 6 NaN 
2 13 8 NaN NaN NaN 
2 14 NaN 10 NaN NaN 
3 15 NaN NaN NaN 12 

In altre parole:

  1. 'id' e 'num' miei indici (di solito, ho visto solo uno 'id' o 'num' essendo l'indice ma ho bisogno di entrambi dal momento che' Sto cercando di recuperare la forma originale non fuso)
  2. 'q' sono le mie colonne
  3. 'v' sono i miei valori nella tabella

Aggiornamento

ho trovato una stretta soluzione da Wes McKinney's blog:

df.pivot_table(index=['id','num'], columns='q') 

     v    
q  a b d z 
id num     
1 10 2 4 NaN NaN 
    12 NaN NaN 6 NaN 
2 13 8 NaN NaN NaN 
    14 NaN 10 NaN NaN 
3 15 NaN NaN NaN 12 

Tuttavia, il formato non è proprio la stessa cosa che voglio sopra.

risposta

9

Sei davvero vicino slaw. Basta rinominare l'indice della colonna su Nessuno e hai ciò che desideri.

df2 = df.pivot_table(index=['id','num'], columns='q') 
df2.columns = df2.columns.droplevel().rename(None) 
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None) 

Nota che la colonna 'v' dovrebbe essere numerici per difetto in modo che possa essere aggregati. In caso contrario, Panda sarà errore fuori con:

DataError: No numeric types to aggregate 

To resolve this, è possibile specificare la propria funzione di aggregazione utilizzando una funzione lambda personalizzato:

df2 = df.pivot_table(index=['id','num'], columns='q', aggfunc= lambda x: x) 
+0

Ahhh, ero così vicino! Sapevo che aveva a che fare con 'df.columns.name', ma non riuscivo a capire come usare' rinominare 'appropriatamente. Grazie per l'aiuto! – slaw

+1

Nota importante: "stretta slaw" suona come "insalata di cavoli". –

0

si avvicinò con una stretta soluzione di

df2 = df.pivot_table(index=['id','num'], columns='q') 
df2.columns = df2.columns.droplevel() 
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None) 

Ancora non riesco a capire come far cadere 'q' dal dataframe

5

Si potrebbe utilizzare set_index e unstack

In [18]: df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index() 
Out[18]: 
q id num a  b d  z 
0 1 10 2.0 4.0 NaN NaN 
1 1 12 NaN NaN 6.0 NaN 
2 2 13 8.0 NaN NaN NaN 
3 2 14 NaN 10.0 NaN NaN 
4 3 15 NaN NaN NaN 12.0 
+0

Questo molto più pulito rispetto alla risposta accettata. Grazie! – kev8484

+0

Grazie. pandas.pivot() con più colonne indice non è così semplice come speravo e questa soluzione ha funzionato. –

1

è possibile rimuovere il nome q.

df1.columns=df1.columns.tolist() 

risposta di Zero + q = rimuovere

df1 = df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index() 
df1.columns=df1.columns.tolist() 

    id num a  b d  z 
0 1 10 2.0 4.0 NaN NaN 
1 1 12 NaN NaN 6.0 NaN 
2 2 13 8.0 NaN NaN NaN 
3 2 14 NaN 10.0 NaN NaN 
4 3 15 NaN NaN NaN 12.0