2013-10-17 3 views
8

ich zwei Datenrahmen haben, die wie folgt aussieht:Pandas: Drehbare mit Multi-Indexdaten

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 

ich schließlich bin versucht, eine Pivot-Tabelle von Bewertung bedeuten für Nutzung zu erhalten von Marke . Oder so etwas wie dieses:

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

Mein Ansatz war es, die Datensätze wie folgt zusammen:

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 

Und dann versuchen, eine Pivot-Tabelle erstellen mit Bewertung als der Wert, eigene als die Reihen und Marke als die Spalten. Aber ich rannte weiter zu wichtigen Themen. Ich habe auch versucht, entweder die Kennzahl- oder die Markenebene zu entstapeln, aber ich kann anscheinend keine Zeilenindexnamen als Pivot-Schlüssel verwenden.

Was mache ich falsch? Gibt es einen besseren Ansatz dafür?

Antwort

4

Ich bin kein Experte in Pandas, so dass die Lösung mehr ungeschickt sein kann, als Sie wollen, aber:

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 

eine andere Lösung, die aber nicht sehr viel verallgemeinerbar (Sie Schleife verwenden können, aber Sie wissen müssen, welche Werte haben Sie in own Datenrahmen haben):

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

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

Danke. Großartig, um eine Lösung zu haben. Du hast Recht, dass ich auf etwas Eleganteres gehofft habe, aber eine Lösung macht mich frei. Ich kann immer eine Funktion schreiben. –

+0

@ Brendon Ich versuche, so viel Zeit wie möglich zu verbringen, um Pandas jetzt zu lernen, werde sehen, was ich nach ein oder zwei Wochen tun kann :) Bitte nicht die Antwort akzeptieren, können einige Gurus mit superelegant Lösung ankommen –

+0

Nun, Ihr Slogan in Ihrem Profil sagt so viel :). Ich werde Ihre Antwort für eine weitere Woche ablehnen. Danke noch einmal. –

3

ich eine neue Antwort auf meine eigene Frage haben (basierend auf Roman anfängliche Antwort). Der Schlüssel ist, den Index auf die erforderliche Dimensionalität zu bringen. Zum Beispiel

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 

Dann ist es einfach, den pivot_table Befehl zu verwenden, um dies in die gewünschte Ergebnis zu drehen:

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 

Und das ist das, was ich suchte. Nochmals vielen Dank an Roman für den Hinweis.