2014-10-05 15 views
19

Mam następującą tabelę. Chcę obliczyć średnią ważoną pogrupowaną według daty w oparciu o poniższy wzór. Mogę to zrobić za pomocą standardowego kodu standardowego, ale zakładając, że dane te znajdują się w ramce danych pandy, czy istnieje jakiś łatwiejszy sposób, aby to osiągnąć, niż poprzez iterację?Obliczyć średnią ważoną przy użyciu pandy/ramki danych

Date  ID  wt  value w_avg 
01/01/2012 100  0.50 60  0.791666667 
01/01/2012 101  0.75 80 
01/01/2012 102  1.00 100 
01/02/2012 201  0.50 100  0.722222222 
01/02/2012 202  1.00 80 

01/01/2012 w_avg = 0,5 * (60/suma (60,80,100)) + .75 * (80/suma (60,80,100)) + 1,0 * (100/suma (60, 80.100))

01/02/2012 w_avg = 0,5 * (100/suma (100,80)) + 1,0 * (80/suma (100,80))

+3

zauważyć, że w przykładzie kolumna „wartość” faktycznie reprezentuje ciężary, a „wag” kolumna wartości do uśrednienia ... – kadee

Odpowiedz

17

myślę, że to zrobić dwa groupbys.

Najpierw obliczyć „średniej ważonej”:

In [11]: g = df.groupby('Date') 

In [12]: df.value/g.value.transform("sum") * df.wt 
Out[12]: 
0 0.125000 
1 0.250000 
2 0.416667 
3 0.277778 
4 0.444444 
dtype: float64 

Jeśli ustawisz jako kolumna, można GroupBy nad nim:

In [13]: df['wa'] = df.value/g.value.transform("sum") * df.wt 

Teraz suma tej kolumnie jest pożądana :

In [14]: g.wa.sum() 
Out[14]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
Name: wa, dtype: float64 

lub potencjalnie:

In [15]: g.wa.transform("sum") 
Out[15]: 
0 0.791667 
1 0.791667 
2 0.791667 
3 0.722222 
4 0.722222 
Name: wa, dtype: float64 
+0

Uwaga: Nie jestem w 100%, jak mam ochotę ponownie użyć g podczas mutowania df, pod warunkiem, że nie mutujesz klucza groupby, myślę, że jest zadbany ... potencjalnie jest to kontrowersyjne ?! IMO pandastyczne. –

+0

udało mi się to zrobić, robiąc coś podobnego, ale zamiast transformować, użyłem tylko groupby (..). Sum(). Czy są jakieś korzyści z używania transformacji? – mike01010

+0

@AndyHayden Obiekt DataFrameGroupBy * odzwierciedlałby zmutowany obiekt, ale w tym przypadku nie mutujesz, więc nic wielkiego. – Jeff

11

Niech najpierw utworzyć dataframe przykład pandas:

In [1]: import numpy as np 

In [2]: import pandas as pd 

In [3]: index = pd.Index(['01/01/2012','01/01/2012','01/01/2012','01/02/2012','01/02/2012'], name='Date') 

In [4]: df = pd.DataFrame({'ID':[100,101,102,201,202],'wt':[.5,.75,1,.5,1],'value':[60,80,100,100,80]},index=index) 

Następnie, średnia 'wagowo' ważone 'wartości' i zgrupowane indeksem otrzymuje się jako:

In [5]: df.groupby(df.index).apply(lambda x: np.average(x.wt, weights=x.value)) 
Out[5]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
dtype: float64 

Alternatywnie można również zdefiniować funkcję:

In [5]: def grouped_weighted_avg(values, weights, by): 
    ...:  return (values * weights).groupby(by).sum()/weights.groupby(by).sum() 

In [6]: grouped_weighted_avg(values=df.wt, weights=df.value, by=df.index) 
Out[6]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
dtype: float64 
+0

Podoba mi się ten jeden o wiele lepiej (ze względu na czytelność), czy są jakieś znaczące występy między tym a rozwiązaniem Andy'ego Haydena? – erb

+2

Czy jest możliwe, że w tym wierszu: W [5]: df.groupby (df.index) .apply (lambda x: np.average (x.wt, wagi = x.value)) x.wt i x. wartość powinna zostać przełączona? – prooffreader

+0

@prooffreader: Jak skomentowałem [powyżej] (http://stackoverflow.com/questions/26205922/calculate-weighted-average-using-a-pandas-dataframe/33054358#comment53928794_26205922): w przykładzie podanym przez pytającego, kolumna "wartość" faktycznie przedstawia wagi, a kolumna "wt" wartości uśrednione. – kadee

5

Uratowałem tabelę w pliku .csv

df=pd.read_csv('book1.csv') 

grouped=df.groupby('Date') 
g_wavg= lambda x: np.average(x.wt, weights=x.value) 
grouped.apply(g_wavg) 
Powiązane problemy