[英]python pandas weighted average with the use of groupby agg()
我希望能夠在 pandas groupby agg() 中使用自定義函數。 我知道有使用apply的選項,但我想要做幾個聚合。 下面是我試圖為加權平均值工作的測試代碼。
Python 代碼
import pandas as pd
import numpy as np
def weighted_avg(df, values, weights):
'''To calculate a weighted average in Pandas. Demo see https://www.statology.org/pandas-weighted-average/
Example: df.groupby('Group Names').apply(w_avg, 'Results', 'AFY')'''
v = df[values]
w = df[weights]
return (v * w).sum() / w.sum()
# below creates a dataframe.
dfr = pd.DataFrame(np.random.randint(1,50,size=(4,4)), columns=list('ABCD'))
dfr['group'] = [1, 1, 0, 1]
print(dfr)
dfr = dfr.groupby('group').agg({'A':'mean', 'B':'sum',
'C': lambda x: weighted_avg(dfr, 'D', 'C')}).reset_index()
print(dfr)
結果 - Output
A B C D group
0 5 2 17 38 1
1 35 30 22 32 1
2 15 18 16 11 0
3 46 6 20 34 1
group A B C
0 0 15.000000 18 29.413333
1 1 28.666667 38 29.413333
問題:加權平均值返回整個表的值,而不是“組”列。 如何通過小組工作獲得加權平均值?
我確實嘗試將 groupby 放在 function 內,如此處所示,但沒有成功。 謝謝你看一看。
您可以使用 lambda 中的x
(具體來說,使用它的.index
來獲取您想要的值)。 例如:
import pandas as pd
import numpy as np
def weighted_avg(group_df, whole_df, values, weights):
v = whole_df.loc[group_df.index, values]
w = whole_df.loc[group_df.index, weights]
return (v * w).sum() / w.sum()
dfr = pd.DataFrame(np.random.randint(1, 50, size=(4, 4)), columns=list("ABCD"))
dfr["group"] = [1, 1, 0, 1]
print(dfr)
dfr = (
dfr.groupby("group")
.agg(
{"A": "mean", "B": "sum", "C": lambda x: weighted_avg(x, dfr, "D", "C")}
)
.reset_index()
)
print(dfr)
印刷:
A B C D group
0 32 2 34 29 1
1 33 32 15 49 1
2 4 43 41 10 0
3 39 33 7 31 1
group A B C
0 0 4.000000 43 10.000000
1 1 34.666667 67 34.607143
編輯:正如@enke 在評論中所述,您可以使用已過濾的 dataframe 調用您的weighted_avg
function:
weighted_avg(dfr.loc[x.index], 'D', 'C')
對於這種事情,我通常會為計算的中間階段添加列:
df['product'] = df['value'] * df['weight']
weighted_avg = sum(df['product']) / sum(df['weight'])
然后您可以像往常一樣進行分組和子集選擇:
df0 = df[df['group']==0]
df1 = df[df['group']==1]
並分別為每個組計算weighted_avg
你寫lambda x: weighted_avg(dfr, 'D', 'C')
這將計算dfr
的加權平均值,即整個表。
如果將其更改為lambda group: weighted_avg(group, "D", "C")
那么我認為它可能會起作用。
(我已將 lambda 變量的名稱更改為group
,因為x
的描述性不強)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.