与熊猫的多个分组

时间:2021-04-20 13:50:17

标签: python pandas dataframe group-by pandas-groupby

我正在尝试使用 Pandas 进行多个 groupby,但我遇到了错误。 我想同时使用日期和类别列。

我想做什么;求同一类别不同基金在同一日期的平均收益。例如,在 2019-03 x 类别平均回报为 0.025。

我的示例 python 代码:

df['benchmark_mean']= df.groupby(["category","date"])["fund_ret"].mean()

我的示例数据帧:

<头>
日期 fund_ticker 类别 fund_ret 导航
2019-02 AAA x 0.05 1000
2019-03 AAA x 0.03 1030
2019-02 BBB y -0.01 ...
2019-03 BBB y 0.07 ...
2019-03 CCC x 0.02 ...

1 个答案:

答案 0 :(得分:0)

您可能需要创建一个名为 benchmark_mean 的新列,该列具有每个组的平均值?,然后您可以执行以下操作:

df.groupby(["category","date"],as_index=False).agg(
       benchmark_mean = pd.NamedAgg(column = 'fund_ret', aggfunc = 'mean'))

输出:

    category       date benchmark_mean
0          x    2019-02          0.050
1          x    2019-03          0.025
2          y    2019-02         -0.010
3          y    2019-03          0.070

如果您希望原始数据框中的新列不改变行,您可以使用 groupby 和如下转换:

df['benchmark_mean'] = df.groupby(['category', 'date'])['fund_ret'].transform('mean')

df 之后的输出:

       date fund_ticker    nav   category   fund_ret    benchmark_mean
0   2019-02         AAA 1000.0         x        0.05             0.050
1   2019-03         AAA 1030.0         x        0.03             0.025
2   2019-02         BBB    NaN         y       -0.01            -0.010
3   2019-03         BBB    NaN         y        0.07             0.070
4   2019-03         CCC    NaN         x        0.02             0.025

为什么我们不能用“apply”代替“transform”?

你可以肯定地使用apply代替transform,你可以得到如下相同的结果:

df_bm = df.groupby(['date', 'category']).apply(lambda x : pd.Series(x['fund_ret'].mean(), ['benchmark_mean'])).reset_index()

df = df.merge(df_bm, on = ['date', 'category'], how = 'left')

您可能想查看 this 漂亮的答案以了解应用和转换之间的差异。

如何获得加权平均值?

我将使用 apply 因为转换一次只对一个系列有效,所以我不能在 groupby 之后使用 [nav, fund_ret]。代码将是:

def weighted_average(x):
    x['nav'] = x['nav'].replace(np.nan, 0)
    if x['nav'].nunique() == 1 and x['nav'].iloc[0] == 0:
        return 0
    return np.average(x['fund_ret'], weights=x['nav'])

df1 = df.groupby(['date', 'category'],as_index=False).apply(lambda x: pd.Series(weighted_average(x), ['weighted_mean']))['weighted_mean'].reset_index()
df.merge(df1, on = ['date', 'category'], how = 'left')

输出(在两个 apply 之后):

       date fund_ticker    nav category fund_ret    benchmark_mean  weighted_mean
0   2019-02        AAA  1000.0       x      0.05             0.050           0.05
1   2019-03        AAA  1030.0       x      0.03             0.025           0.03
2   2019-02        BBB     NaN       y     -0.01            -0.010            NaN
3   2019-03        BBB     NaN       y      0.07             0.070            NaN
4   2019-03        CCC     NaN       x      0.02             0.025           0.03
相关问题