2013-10-17 7 views
8

Ho due dataframes che assomiglia a questo:Pandas: piroettanti con i dati multi-indice

rating 
    BMW Fiat Toyota 
0 7  2  3 
1 8  1  8 
2 9 10  7 
3 8  3  9 

own 
    BMW Fiat Toyota 
0 1  1  0 
1 0  1  1 
2 0  0  1 
3 0  1  1 

sto in ultima analisi, cercando di ottenere una tabella pivot di significa voto per utilizzo da marca . O qualcosa di simile:

  BMW Fiat Toyota 
Usage       
0  8.333333 10  3 
1  7.000000  2  8 

Il mio approccio è stato quello di unire le serie di dati di questo tipo:

Measure Rating    Own    
Brand  BMW Fiat Toyota BMW Fiat Toyota 
0    7  2  3 1  1  0 
1    8  1  8 0  1  1 
2    9 10  7 0  0  1 
3    8  3  9 0  1  1 

e quindi tentare di creare una tabella pivot utilizzando voto come valore, proprio come il righe e marchio come le colonne. Ma ho continuato a correre su questioni chiave. Ho anche tentato di rimuovere i livelli di misura o di marca, ma non riesco a utilizzare i nomi degli indici delle righe come chiavi di rotazione.

Cosa sto sbagliando? C'è un approccio migliore a questo?

risposta

4

Io non sono un esperto di Panda, per cui la soluzione può essere più goffo di quanto si vuole, ma:

rating = pd.DataFrame({"BMW":[7, 8, 9, 8], "Fiat":[2, 1, 10, 3], "Toyota":[3, 8, 7,9]}) 
own = pd.DataFrame({"BMW":[1, 0, 0, 0], "Fiat":[1, 1, 0, 1], "Toyota":[0, 1, 1, 1]}) 

r = rating.unstack().reset_index(name='value') 
o = own.unstack().reset_index(name='value') 
res = DataFrame({"Brand":r["level_0"], "Rating": r["value"], "Own": o["value"]}) 
res = res.groupby(["Own", "Brand"]).mean().reset_index() 
res.pivot(index="Own", columns="Brand", values="Rating") 

# result 
# Brand  BMW Fiat Toyota 
# Own       
# 0  8.333333 10  3 
# 1  7.000000  2  8 

un'altra soluzione, anche se non molto generalizzabile (si può usare per ciclo, ma si devono sapere che i valori avete in own dataframe):

d = [] 
for o in (0, 1): 
    t = rating[own == o] 
    t["own"] = o 
    d.append(t) 

res = pd.concat(d).groupby("own").mean() 
+0

Grazie. Ottimo per avere una soluzione. Hai ragione che speravo in qualcosa di più elegante, ma una soluzione mi ha bloccato. Posso sempre scrivere una funzione. –

+0

@Brendon Sto cercando di dedicare tutto il tempo che posso per imparare Pandas ora, vedrò cosa posso fare dopo una o due settimane :) Si prega di non accettare la risposta, potrebbe essere che alcuni guru arriveranno con una soluzione superelegante –

+0

Bene, la tua tagline sul tuo profilo dice tanto :). Continuerò ad accettare la tua risposta per un'altra settimana. Grazie ancora. –

3

ho una nuova risposta alla mia domanda (in base alla risposta iniziale di Roman). La chiave è ottenere l'indice con la dimensionalità richiesta. Per esempio

rating.columns.names = ["Brand"] 
rating.index.names = ["n"] 
print rating 

Brand BMW Fiat Toyota 
n      
0  7  2  3 
1  8  1  8 
2  9 10  7 
3  8  3  9 

own.columns.names = ["Brand"] 
own.index.names = ["n"] 
print own 

Brand BMW Fiat Toyota 
n      
0  1  1  0 
1  0  1  1 
2  0  0  1 
3  0  1  1 

merged = pd.merge(own.unstack().reset_index(name="Own"), 
        rating.unstack().reset_index(name="Rating")) 
print merged 

    Brand n Own Rating 
0  BMW 0 1  7 
1  BMW 1 0  8 
2  BMW 2 0  9 
3  BMW 3 0  8 
4  Fiat 0 1  2 
5  Fiat 1 1  1 
6  Fiat 2 0  10 
7  Fiat 3 1  3 
8 Toyota 0 0  3 
9 Toyota 1 1  8 
10 Toyota 2 1  7 
11 Toyota 3 1  9 

allora è facile da usare il comando pivot_table di trasformare questo nel risultato desiderato:

print merged.pivot_table(rows="Brand", cols="Own", values="Rating") 

Own    0 1 
Brand    
BMW  8.333333 7 
Fiat 10.000000 2 
Toyota 3.000000 8 

E questo è quello che stavo cercando. Grazie ancora a Roman per aver indicato la strada.