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

Pandas按指定列分组后统计分组总数及其他列值子计数

问题:如何在Pandas分组统计中获取多列不同取值的子计数?

我有如下DataFrame:

import pandas as pd

df = pd.DataFrame({
  'org':['a','a','a','a','b','b'],
  'product_version':['bpm','bpm','bpm','bpm','ppp','ppp'],
  'release_date':['2022-07','2022-07','2022-07','2022-07','2022-08','2022-08'],
  'date_avail':['no','no','no','yes','no','no'],
  'status':['green','green','yellow','yellow','green','green']
})

数据展示如下:

org product_version release_date date_avail  status
0   a             bpm      2022-07         no   green
1   a             bpm      2022-07         no   green
2   a             bpm      2022-07         no  yellow
3   a             bpm      2022-07        yes  yellow
4   b             ppp      2022-08         no   green
5   b             ppp      2022-08         no   green

我已经实现按['org','product_version','release_date']列分组并统计分组总数:

print(df.groupby(['org','product_version','release_date']).size())

输出结果:

org  product_version  release_date
a    bpm              2022-07         4
b    ppp              2022-08         2

现在需要进一步获取分组中date_avail、status列不同取值的子计数,最终期望得到如下格式的结果:

org product release_date total number_of_no number_of_yes number_of_green number_of_yellow
a   bpm     2022-07      4     3             1            2               2
b   ppp     2022-08      2     2             0            2               0 

解决方案

可以通过分组聚合结合自定义统计逻辑实现,以下是几种简洁的方法:

方法1:分组聚合+多表合并

分别统计总计数、各列取值数,再合并结果:

# 计算分组总计数
total_counts = df.groupby(['org','product_version','release_date']).size().rename('total').reset_index()

# 统计date_avail列各取值数量
date_counts = df.groupby(['org','product_version','release_date'])['date_avail'].value_counts()\
    .unstack(fill_value=0).add_prefix('number_of_').reset_index()

# 统计status列各取值数量
status_counts = df.groupby(['org','product_version','release_date'])['status'].value_counts()\
    .unstack(fill_value=0).add_prefix('number_of_').reset_index()

# 合并所有统计结果
result = total_counts.merge(date_counts, on=['org','product_version','release_date'])\
    .merge(status_counts, on=['org','product_version','release_date'])

# 重命名列匹配期望格式
result = result.rename(columns={'product_version': 'product'})

print(result)

输出结果:

org product release_date  total  number_of_no  number_of_yes  number_of_green  number_of_yellow
0   a     bpm      2022-07      4             3              1                2                 2
1   b     ppp      2022-08      2             2              0                2                 0

方法2:交叉表一次性生成统计结果

利用pd.crosstab直接关联分组维度和目标列取值:

# 生成交叉表,行是分组维度,列是目标列的取值
cross_tab = pd.crosstab(
    index=[df['org'], df['product_version'], df['release_date']],
    columns=[df['date_avail'], df['status']],
    margins=False,
    dropna=False
).fillna(0).astype(int)

# 重命名列名
cross_tab.columns = cross_tab.columns.map(lambda x: f'number_of_{x[0]}' if pd.isna(x[1]) else f'number_of_{x[1]}')
# 补充总计数列
cross_tab['total'] = cross_tab.sum(axis=1)

# 重置索引并调整列顺序
result = cross_tab.reset_index().rename(columns={'product_version': 'product'})
result = result[['org','product','release_date','total','number_of_no','number_of_yes','number_of_green','number_of_yellow']]

print(result)

方法3:哑变量转换+分组求和

将目标列转为哑变量后直接分组求和,适合取值固定的场景:

# 将date_avail和status转为哑变量
dummy_df = pd.get_dummies(df, columns=['date_avail', 'status'], prefix='number_of', prefix_sep='_')

# 分组求和并计算总计数
result = dummy_df.groupby(['org','product_version','release_date']).sum().reset_index()
result['total'] = result.filter(like='number_of_').sum(axis=1)

# 调整列名和顺序
result = result.rename(columns={'product_version': 'product'})
result = result[['org','product','release_date','total','number_of_no','number_of_yes','number_of_green','number_of_yellow']]

print(result)

内容的提问来源于stack exchange,提问作者moth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:35:28