2013-10-17 12 views
8

Mam dwa dataframes który wygląda następująco:Pandy: Obrotowa z danymi multi-indeksowych

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 

Ja ostatecznie próbuje dostać stolik obrotowy z średnia ocena dla użytkowania przez marki . Albo coś takiego:

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

Moje podejście było scalić zestawów danych tak:

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 

A potem próbować utworzyć tabeli przestawnej za pomocą rating jako wartość, własny jako wiersze i marka jako kolumny. Ale ciągle biegałem do kluczowych kwestii. Podjęto również próbę rozpakowania poziomu miary lub marki, ale nie mogę użyć nazw indeksu wiersza jako kluczy przestawnych.

Co robię źle? Czy istnieje lepsze podejście do tego?

Odpowiedz

4

Nie jestem ekspertem w Pandy, więc rozwiązanie może być bardziej niezdarna niż chcesz, ale:

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 

inne rozwiązanie, choć nie bardzo uogólnione (można użyć dla pętli, ale trzeba wiedzieć, jakie wartości masz w 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

Dzięki. Wspaniale mieć rozwiązanie. Masz rację, że liczyłem na coś bardziej eleganckiego, ale rozwiązanie odblokowuje mnie. Zawsze mogę napisać funkcję. –

+0

@Brendon Próbuję spędzić tyle czasu, ile mogę, aby nauczyć się Pand, teraz zobaczę, co mogę zrobić po tygodniu lub dwóch :) Proszę nie akceptować odpowiedzi, może niektórzy guru przyjeżdżają z superelegantnym rozwiązaniem –

+0

Twój slogan na twoim profilu mówi tyle :). Będę wstrzymywał przyjmowanie twojej odpowiedzi przez kolejny tydzień. Dzięki jeszcze raz. –

3

mam nową odpowiedź na moje własne pytanie (na podstawie wstępnej odpowiedzi Romana). Kluczem jest uzyskanie indeksu o wymaganej wymiarowości. Na przykład

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 

Wtedy to łatwy w użyciu komendy pivot_table aby przekształcić pożądanego rezultatu:

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 

I to jest to, czego szukałem. Jeszcze raz dziękuję Romanowi za wskazanie drogi.