python pandas 使用 groupby agg() 的加权平均值
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)
结果-输出
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
问题: 加权平均值返回整个 table 而不是 'group' 列的值。我怎样才能得到分组工作的加权平均值?
我确实尝试将 groupby 放在 shown here 之类的函数中,但没有成功。
感谢您的观看。
您可以使用 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 在评论中所述,您可以使用已过滤的数据框调用您的 weighted_avg
函数:
weighted_avg(dfr.loc[x.index], 'D', 'C')
你写的地方
lambda x: weighted_avg(dfr, 'D', 'C')
这将计算 dfr
的加权平均值,即整个 table。
如果你把它改成
lambda group: weighted_avg(group, "D", "C")
那么我认为它可能会起作用。
(我已将 lambda 变量的名称更改为 group
,因为 x
的描述性不强)
对于这种事情,我通常会在计算的中间阶段添加列:
df['product'] = df['value'] * df['weight']
weighted_avg = sum(df['product']) / sum(df['weight'])
然后您可以像往常一样进行分组和 subset-selction:
df0 = df[df['group']==0]
df1 = df[df['group']==1]
并为每组分别计算weighted_avg
我希望能够在 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)
结果-输出
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
问题: 加权平均值返回整个 table 而不是 'group' 列的值。我怎样才能得到分组工作的加权平均值?
我确实尝试将 groupby 放在 shown here 之类的函数中,但没有成功。 感谢您的观看。
您可以使用 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 在评论中所述,您可以使用已过滤的数据框调用您的 weighted_avg
函数:
weighted_avg(dfr.loc[x.index], 'D', 'C')
你写的地方
lambda x: weighted_avg(dfr, 'D', 'C')
这将计算 dfr
的加权平均值,即整个 table。
如果你把它改成
lambda group: weighted_avg(group, "D", "C")
那么我认为它可能会起作用。
(我已将 lambda 变量的名称更改为 group
,因为 x
的描述性不强)
对于这种事情,我通常会在计算的中间阶段添加列:
df['product'] = df['value'] * df['weight']
weighted_avg = sum(df['product']) / sum(df['weight'])
然后您可以像往常一样进行分组和 subset-selction:
df0 = df[df['group']==0]
df1 = df[df['group']==1]
并为每组分别计算weighted_avg