如何用更Pythonic的方式实现Pandas分组后统计计数与归一化计数?
更简洁的实现方式
这里有两种更Pythonic的方法来实现你的需求,避免拼接两个DataFrame的繁琐操作:
方法1:先计数再计算归一化值
先按store和item分组得到计数,再通过transform计算组内占比:
import pandas as pd import numpy as np # 构造示例数据 df = pd.DataFrame({ 'store': ['Store1', 'Store2', 'Store3', 'Store2', 'Store2', 'Store3', 'Store1', 'Store1', 'Store3'], 'item': ['table', 'chair', 'chair', 'table', 'chair', 'table', 'chair', 'table', np.nan] }) # 1. 分组计数 result = df.groupby(['store', 'item'], dropna=False).size().rename('count').reset_index() # 2. 计算每个store组内的归一化占比 result['normcount'] = result.groupby('store')['count'].transform(lambda x: x / x.sum()) # 3. 还原多级索引(和原输出格式一致) result = result.set_index(['store', 'item']) print(result)
输出结果:
count normcount store item Store1 table 2 0.666667 chair 1 0.333333 Store2 chair 2 0.666667 table 1 0.333333 Store3 chair 1 0.333333 table 1 0.333333 NaN 1 0.333333
方法2:自定义函数结合apply
直接在groupby('store')后应用自定义函数,一次性返回计数和归一化结果:
def get_counts_and_norm(series): # 同时获取计数和归一化值 count_series = series.value_counts(dropna=False) norm_series = series.value_counts(normalize=True, dropna=False) # 返回包含两列的DataFrame return pd.DataFrame({'count': count_series, 'normcount': norm_series}) result = df.groupby('store')['item'].apply(get_counts_and_norm) print(result)
这个方法的输出和你原代码的结果完全一致,而且代码更紧凑。
为什么你的原有agg写法失效?
你之前尝试的groupby(['store','item']).agg(...)思路有误:
- 当按
store和item同时分组时,每个子组的item都是单一值(或NaN),此时value_counts无法统计出有效分布 - 即使传递函数,
agg中直接写pd.value_counts(normalize=True)是错误的,因为这会立即执行函数而不是传递函数对象,正确的方式是用lambda包装,但这里的分组逻辑本身就不对
正确的分组逻辑应该是先按store分组,再对每个组内的item列做value_counts,而不是同时按两个字段分组。
内容的提问来源于stack exchange,提问作者Guillaume-ds
相关产品推荐
相关产品推荐

