2017-07-17 10 views
2

Bei dem folgenden Datenrahmen:Pandas GROUPBY Mit Gewicht

import pandas as pd 
d=pd.DataFrame({'Age':[18,20,20,56,56],'Race':['A','A','A','B','B'],'Response':[3,2,5,6,2],'Weight':[0.5,0.5,0.5,1.2,1.2]}) 
d 
    Age  Race Response Weight 
0 18  A  3   0.5 
1 20  A  2   0.5 
2 20  A  5   0.5 
3 56  B  6   1.2 
4 56  B  2   1.2 

Ich weiß, dass ich eine Gruppe-by, um die Zählung zu erhalten nach Alter und Rasse wie diese anwenden kann:

d.groupby(['Age','Race'])['Response'].count() 
Age Race 
18 A  1 
20 A  2 
56 B  2 
Name: Response, dtype: int64 

Aber ich Ich möchte die "Gewichtung" -Spalte verwenden, um die Fälle so zu gewichten, dass die ersten 3 Zeilen als 0,5 statt 1 zählen und die letzten beiden als 1,2 zählen. Also, wenn nach Alter und Rasse Gruppierung sollte ich habe folgendes:

Age Race 
18 A  0.5 
20 A  1 
56 B  2.4 
Name: Response, dtype: int64 

Dies ist ähnlich der „Fälle gewichten“ Option in SPSS zu verwenden. Ich weiß, es ist möglich, in R, und ich habe eine viel versprechende Bibliothek in Python zu sehen hier (obwohl der aktuelle Build fehlschlägt):

https://github.com/InContextSolutions/PandaSurvey

und PySal (nicht sicher, ob es hier anwendbar ist)

... aber ich frage mich, ob es irgendwie irgendwie in der Gruppe gemacht werden kann.

Vielen Dank im Voraus!

Antwort

3

Wenn ich richtig verstehe, suchen Sie nur nach .sum() mit den Gewichten.

d.groupby(['Age', 'Race']).Weight.sum() 

## Age Race 
## 18 A  0.5 
## 20 A  1.0 
## 56 B  2.4 
## Name: Weight, dtype: float64 
+0

Danke, @Mitch zu tun! Das war direkt vor meiner Nase. –

+0

@DanceParty Gern geschehen! – miradulo

2

Nicht ganz offensichtlich ... aber eine unterhaltsame Art und Weise es mit pd.factorize und np.bincount

f, u = pd.factorize(
    [tuple(row) for row in d[['Age', 'Race']].values.tolist()] 
) 

pd.Series(
    np.bincount(f, d.Weight.values), 
    pd.MultiIndex.from_tuples(u, names=['Age', 'Race']) 
) 

Age Race 
18 A  0.5 
20 A  1.0 
56 B  2.4 
dtype: float64 
+1

"Nicht genau offensichtlich" könnte eine leichte Untertreibung sein;) aber das ist sauber. – miradulo