<p>我在数据表示方面也遇到了类似的问题,并为groupby提供了下面的helper函数和小计。在</p>
<p>通过这个过程,可以为任意数量的groupby列生成小计,但是输出数据的格式不同。不是将小计放在它们自己的列中,而是将每个小计添加到数据帧中一个额外的行。在</p>
<p>对于交互式数据探索和分析,我发现这非常有帮助,因为只需几行代码就可以得到小计</p>
<pre><code>def get_subtotals(frame, columns, aggvalues, subtotal_level):
if subtotal_level == 0:
return frame.groupby(columns, as_index=False).agg(aggvalues)
elif subtotal_level == len(columns):
return pd.DataFrame(frame.agg(aggvalues)).transpose().assign(
**{c: np.nan for i, c in enumerate(columns)}
)
return frame.groupby(
columns[:subtotal_level],
as_index=False
).agg(aggvalues).assign(
**{c: np.nan for i, c in enumerate(columns[subtotal_level:])}
)
def groupby_with_subtotals(frame, columns, aggvalues, grand_totals=False, totals_position='last'):
gt = 1 if grand_totals else 0
out = pd.concat(
[get_subtotals(df, columns, aggvalues, i)
for i in range(len(columns)+gt)]
).sort_values(columns, na_position=totals_position)
out[columns] = out[columns].fillna('total')
return out.set_index(columns)
</code></pre>
<p>正在从<a href="https://stackoverflow.com/a/49214387/2570261">Gabriel A's answer</a>恢复数据帧创建代码</p>
^{pr2}$
<p>首先需要添加<code>seg</code>列</p>
<pre><code>df['seg'] = df.groupby(['Participant_n', 'Task_n']).cumcount() + 1
</code></pre>
<p>然后我们可以像这样使用<code>groupby_with_subtotals</code>。另外,请注意,您可以将小计放在顶部,还可以通过传入<code>grand_totals=True, totals_position='first'</code>来包含总计</p>
<pre><code>groupby_columns = ['Participant_n', 'Task_n', 'seg']
groupby_aggs = {'val': 'sum', 'dur': 'sum'}
aggdf = groupby_with_subtotals(df, groupby_columns, groupby_aggs)
aggdf
# outputs
dur val
Participant_n Task_n seg
1 1.0 1.0 83 25
2.0 68 4
3.0 987 9
total 1138 38
2.0 1.0 98 98
2.0 4 84
total 102 182
total total 1240 220
2 1.0 1.0 21 9
total 21 9
2.0 1.0 6 15
2.0 6 185
3.0 4 18
total 16 218
3.0 1.0 12 8
total 12 8
total total 49 235
3 1.0 1.0 78 7
2.0 88 12
total 166 19
2.0 1.0 48 12
total 48 12
total total 214 31
</code></pre>
<p>这里,小计行用<code>total</code>标记,最左边的<code>total</code>表示小计级别。在</p>
<p>一旦创建了聚合数据帧,就可以使用<code>loc</code>访问小计。示例:</p>
<pre><code>aggdf.loc[1,'total','total']
# outputs:
dur 1240
val 220
Name: (1, total, total), dtype: int64
</code></pre>