按加权平均值分组,允许零值权重
Group by weighted mean, allowing for zero value weights
我想在 group-by 语句中取列的加权平均值,就像这样
import pandas as pd
import numpy as np
df = pd.DataFrame({'group': ['A', 'A', 'A', 'B', 'B', 'B'],
'value': [0.4, 0.3, 0.2, 0.4, 0.3, 0.2],
'weight': [2, 2, 4, 3, 1, 2]})
df_grouped = df.groupby('group')[['value', 'weight']].apply(lambda x: sum(x['value']*x['weight'])/sum(x['weight']))
df_grouped
Out[17]:
group
A 0.275000
B 0.316667
dtype: float64
到目前为止一切都很好。 但是,在某些情况下权重总和为零,例如
df = pd.DataFrame({'group': ['A', 'A', 'A', 'B', 'B', 'B'],
'value': [0.4, 0.3, 0.2, 0.4, 0.3, 0.2],
'weight': [1, 2, 3, 0, 0, 0]})
在这种情况下,我想采用简单的方法。由于被零除,上面的表达式显然失败了。
我目前使用的方法是在权重和为1的地方将权重替换为1
df_temp = df.groupby('group')['weight'].transform('sum').reset_index()
df['new_weight'] = np.where(df_temp['weight']==0, 1, df['weight'])
df_grouped = df.groupby('group')[['value', 'new_weight']].apply(lambda x: sum(x['value']*x['new_weight'])/sum(x['new_weight']))
这是一个不错的解决方案。但这可以通过一行来实现吗?例如一些特殊功能?
如果您需要在一行中完成它,可以使用 lambda 中的三元运算符检查 Group By Sum 是否等于零,如下所示。如果总和分组为零,则使用常规平均值。
df.groupby('group')[['value', 'weight']].apply(lambda x:sum(x['value'])/len(x['weight']) if (sum(x['weight'])) == 0 else sum(x['value']*x['weight'])/sum(x['weight']))
group
A 0.266667
B 0.300000
dtype: float64
上面片段的常规均值计算可以进一步缩小如下。
df.groupby('group')[['value', 'weight']].apply(lambda x:x['value'].mean() if (sum(x['weight'])) == 0 else sum(x['value']*x['weight'])/sum(x['weight']))
但是,我认为这种单行代码会降低代码的可读性。
我想在 group-by 语句中取列的加权平均值,就像这样
import pandas as pd
import numpy as np
df = pd.DataFrame({'group': ['A', 'A', 'A', 'B', 'B', 'B'],
'value': [0.4, 0.3, 0.2, 0.4, 0.3, 0.2],
'weight': [2, 2, 4, 3, 1, 2]})
df_grouped = df.groupby('group')[['value', 'weight']].apply(lambda x: sum(x['value']*x['weight'])/sum(x['weight']))
df_grouped
Out[17]:
group
A 0.275000
B 0.316667
dtype: float64
到目前为止一切都很好。 但是,在某些情况下权重总和为零,例如
df = pd.DataFrame({'group': ['A', 'A', 'A', 'B', 'B', 'B'],
'value': [0.4, 0.3, 0.2, 0.4, 0.3, 0.2],
'weight': [1, 2, 3, 0, 0, 0]})
在这种情况下,我想采用简单的方法。由于被零除,上面的表达式显然失败了。
我目前使用的方法是在权重和为1的地方将权重替换为1
df_temp = df.groupby('group')['weight'].transform('sum').reset_index()
df['new_weight'] = np.where(df_temp['weight']==0, 1, df['weight'])
df_grouped = df.groupby('group')[['value', 'new_weight']].apply(lambda x: sum(x['value']*x['new_weight'])/sum(x['new_weight']))
这是一个不错的解决方案。但这可以通过一行来实现吗?例如一些特殊功能?
如果您需要在一行中完成它,可以使用 lambda 中的三元运算符检查 Group By Sum 是否等于零,如下所示。如果总和分组为零,则使用常规平均值。
df.groupby('group')[['value', 'weight']].apply(lambda x:sum(x['value'])/len(x['weight']) if (sum(x['weight'])) == 0 else sum(x['value']*x['weight'])/sum(x['weight']))
group
A 0.266667
B 0.300000
dtype: float64
上面片段的常规均值计算可以进一步缩小如下。
df.groupby('group')[['value', 'weight']].apply(lambda x:x['value'].mean() if (sum(x['weight'])) == 0 else sum(x['value']*x['weight'])/sum(x['weight']))
但是,我认为这种单行代码会降低代码的可读性。