分组 totals/subtotals
groupby with totals/subtotals
假设我有以下数据框
Strategy AssetClass Symbol Value Indicator
Strat1 OPT OPT_ABC1 50 -0.3
Strat1 OPT OPT_ABC2 50 1.5
Strat1 STK STK_ABC 50 2.7
Strat2 STK STK_XYZ 70 -3.8
Strat3 OPT OPT_MNO 25 10
我想制作以下内容:
Strategy AssetClass Symbol Value Indicator
Strat1 3.9
OPT 1.2
OPT_ABC1 50 -0.3
OPT_ABC2 50 1.5
STK 2.7
STK_ABC 50 2.7
Strat2 -3.8
STK -3.8
STK_XYZ 70 -3.8
Strat3 10
OPT 10
OPT_MNO 25 10
因此,我们的想法是按照每个策略的总计重新排列数据,然后是资产类别,然后是每个交易品种。 “值”列在符号级别可用,而“指标”列是子组的总和。
我考虑过使用 pd.pivot_table,但它似乎无法生成我正在寻找的 totals/sub_totals。我想我应该 use/loop 在 pd.groupby 策略上,然后在 Strategy/AssetClass 上循环另一个 groupby,然后在 Strategy/AssetClass/Symbol
上循环一个 groupby
df 是上面的数据框,我这样做了:
container = []
for label, _df in df.groupby(['Strategy', 'AssetClass', 'Symbol']):
_df.loc[f'{label}'] = _df[['Indicator']].sum()
container.append(_df)
df_res = pd.concat(container)
print(df_res.fillna(''))
我的问题是小计是插入到对应行之后,标签作为索引。此外,我想不出添加其他 lopps(即小计)easy/pythonic 的方法
您可以按不同的列进行聚合,因此为了提高性能,最好不要使用嵌套 groupby.apply
,而是使用多重聚合,最后按 concat
, change order of columns by DataFrame.reindex
将它们连接在一起,最后对前 2 列进行排序:
df1 = df.groupby(['Strategy', 'AssetClass', 'Symbol'], as_index=False).sum()
df2 = (df1.groupby(['Strategy', 'AssetClass'], as_index=False)['Indicator'].sum()
.assign(Symbol = ''))
df3 = (df1.groupby('Strategy', as_index=False)['Indicator'].sum()
.assign(AssetClass = ''))
df = (pd.concat([df3, df2, df1])
.reindex(df.columns, axis=1)
.fillna('')
.sort_values(['Strategy','AssetClass'], ignore_index=True))
print (df)
Strategy AssetClass Symbol Value Indicator
0 Strat1 3.9
1 Strat1 OPT 1.2
2 Strat1 OPT OPT_ABC1 50.0 -0.3
3 Strat1 OPT OPT_ABC2 50.0 1.5
4 Strat1 STK 2.7
5 Strat1 STK STK_ABC 50.0 2.7
6 Strat2 -3.8
7 Strat2 STK -3.8
8 Strat2 STK STK_XYZ 70.0 -3.8
9 Strat3 10.0
10 Strat3 OPT 10.0
11 Strat3 OPT OPT_MNO 25.0 10.0
假设我有以下数据框
Strategy AssetClass Symbol Value Indicator
Strat1 OPT OPT_ABC1 50 -0.3
Strat1 OPT OPT_ABC2 50 1.5
Strat1 STK STK_ABC 50 2.7
Strat2 STK STK_XYZ 70 -3.8
Strat3 OPT OPT_MNO 25 10
我想制作以下内容:
Strategy AssetClass Symbol Value Indicator
Strat1 3.9
OPT 1.2
OPT_ABC1 50 -0.3
OPT_ABC2 50 1.5
STK 2.7
STK_ABC 50 2.7
Strat2 -3.8
STK -3.8
STK_XYZ 70 -3.8
Strat3 10
OPT 10
OPT_MNO 25 10
因此,我们的想法是按照每个策略的总计重新排列数据,然后是资产类别,然后是每个交易品种。 “值”列在符号级别可用,而“指标”列是子组的总和。
我考虑过使用 pd.pivot_table,但它似乎无法生成我正在寻找的 totals/sub_totals。我想我应该 use/loop 在 pd.groupby 策略上,然后在 Strategy/AssetClass 上循环另一个 groupby,然后在 Strategy/AssetClass/Symbol
上循环一个 groupbydf 是上面的数据框,我这样做了:
container = []
for label, _df in df.groupby(['Strategy', 'AssetClass', 'Symbol']):
_df.loc[f'{label}'] = _df[['Indicator']].sum()
container.append(_df)
df_res = pd.concat(container)
print(df_res.fillna(''))
我的问题是小计是插入到对应行之后,标签作为索引。此外,我想不出添加其他 lopps(即小计)easy/pythonic 的方法
您可以按不同的列进行聚合,因此为了提高性能,最好不要使用嵌套 groupby.apply
,而是使用多重聚合,最后按 concat
, change order of columns by DataFrame.reindex
将它们连接在一起,最后对前 2 列进行排序:
df1 = df.groupby(['Strategy', 'AssetClass', 'Symbol'], as_index=False).sum()
df2 = (df1.groupby(['Strategy', 'AssetClass'], as_index=False)['Indicator'].sum()
.assign(Symbol = ''))
df3 = (df1.groupby('Strategy', as_index=False)['Indicator'].sum()
.assign(AssetClass = ''))
df = (pd.concat([df3, df2, df1])
.reindex(df.columns, axis=1)
.fillna('')
.sort_values(['Strategy','AssetClass'], ignore_index=True))
print (df)
Strategy AssetClass Symbol Value Indicator
0 Strat1 3.9
1 Strat1 OPT 1.2
2 Strat1 OPT OPT_ABC1 50.0 -0.3
3 Strat1 OPT OPT_ABC2 50.0 1.5
4 Strat1 STK 2.7
5 Strat1 STK STK_ABC 50.0 2.7
6 Strat2 -3.8
7 Strat2 STK -3.8
8 Strat2 STK STK_XYZ 70.0 -3.8
9 Strat3 10.0
10 Strat3 OPT 10.0
11 Strat3 OPT OPT_MNO 25.0 10.0