2013-10-09 7 views
8

Sto provando a fare un pivot di una tabella contenente stringhe come risultato.panda - pivot_table con valori non numerici? (DataError: nessun tipo numerico da aggregare)

import pandas as pd 

df1 = pd.DataFrame({'index' : range(8), 
'variable1' : ["A","A","B","B","A","B","B","A"], 
'variable2' : ["a","b","a","b","a","b","a","b"], 
'variable3' : ["x","x","x","y","y","y","x","y"], 
'result': ["on","off","off","on","on","off","off","on"]}) 

df1.pivot_table(values='result',rows='index',cols=['variable1','variable2','variable3']) 

Ma ottengo: DataError: No numeric types to aggregate.

Questo funziona come previsto quando cambio i valori di risultato ai numeri:

df2 = pd.DataFrame({'index' : range(8), 
'variable1' : ["A","A","B","B","A","B","B","A"], 
'variable2' : ["a","b","a","b","a","b","a","b"], 
'variable3' : ["x","x","x","y","y","y","x","y"], 
'result': [1,0,0,1,1,0,0,1]}) 

df2.pivot_table(values='result',rows='index',cols=['variable1','variable2','variable3']) 

E ho quello che mi serve:

variable1 A    B  
variable2 a  b  a b 
variable3 x y x y x y 
index        
0   1 NaN NaN NaN NaN NaN 
1   NaN NaN 0 NaN NaN NaN 
2   NaN NaN NaN NaN 0 NaN 
3   NaN NaN NaN NaN NaN 1 
4   NaN 1 NaN NaN NaN NaN 
5   NaN NaN NaN NaN NaN 0 
6   NaN NaN NaN NaN 0 NaN 
7   NaN NaN NaN 1 NaN NaN 

so di poter mappare le stringhe in valori numerici e poi invertire l'operazione, ma forse c'è una soluzione più elegante?

risposta

23

La mia risposta originale era basata su Panda 0.14.1, e da allora, molte cose sono cambiate nella funzione tabella_pivot (file -> Indice, Cols -> Colonne ...)

Inoltre, sembra che il trucco lambda originale che ho postato non funziona più su Pandas 0.18. Devi fornire una funzione di riduzione (anche se è min, max o media). Ma anche questo sembrava improprio - perché non riduciamo il set di dati, semplicemente trasformandola .... Così ho guardato di più a disimpilamento ...

import pandas as pd 

df1 = pd.DataFrame({'index' : range(8), 
'variable1' : ["A","A","B","B","A","B","B","A"], 
'variable2' : ["a","b","a","b","a","b","a","b"], 
'variable3' : ["x","x","x","y","y","y","x","y"], 
'result': ["on","off","off","on","on","off","off","on"]}) 

# these are the columns to end up in the multi-index columns. 
unstack_cols = ['variable1', 'variable2', 'variable3'] 

In primo luogo, impostare un indice dei dati utilizzando l'indice + le colonne che vuoi impilare, quindi chiama unstack usando il livello arg.

df1.set_index(['index'] + unstack_cols).unstack(level=unstack_cols) 

Il dataframe risultante è inferiore.

enter image description here

+0

Finalmente una soluzione per la sostituzione delle modifiche pivot() nei panda 0.17.1 – camdenl

+0

@RandallGoodwin, mi rendo conto che questa domanda ha due anni, ma sto ricevendo l'errore "ValueError: la funzione non si riduce "Usando il tuo lambda, dalla cima della tua testa, sapresti perché? – RustyShackleford

+1

Un'altra idea: se si hanno potenzialmente più valori che appaiono, si possono concatre stringhe facendo il tuo 'aggfunc = lambda x:" ".join ([str (y) per y in x])' – dllahr

2

Penso che il miglior compromesso sia quello di sostituire on/off con True/False, che consentirà ai panda di "capire" meglio i dati e di agire in modo intelligente, atteso.

df2 = df1.replace({'on': True, 'off': False}) 

Nella tua domanda hai sostanzialmente ammesso. La mia risposta è, non penso che ci sia un modo migliore, e dovresti sostituire 'on'/'off' comunque per quello che verrà dopo.

Come sottolinea Andy Hayden nei commenti, si otterranno prestazioni migliori se si sostituisce on/off con 1/0.

+1

+1, anche se può essere meglio usare 1 e 0 in modo dataframe trovi galleggiante piuttosto che oggetto dtype :) –

+0

ho mai pensato. Buon punto –

+0

OK, sembra abbastanza chiaro :) –