You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用更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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 10:32:13