0

0

Pandas 多列分组统计与结果透视:实现交叉计数表

花韻仙語

花韻仙語

发布时间:2025-10-03 12:05:10

|

237人浏览过

|

来源于php中文网

原创

Pandas 多列分组统计与结果透视:实现交叉计数表

本文详细介绍了如何使用 Pandas 在多个列上进行分组,并对另一列的唯一值进行计数,最终将计数结果以宽格式(类似透视表)呈现。通过 groupby().size().unstack() 组合操作,可以高效地将分类计数转换为结构清晰的报表,避免了传统 crosstab 或简单 pivot 的局限性,特别适用于需要按多个维度进行分类汇总的场景。

场景描述与挑战

在数据分析中,我们经常需要对数据集进行多维度统计。一个常见的需求是,在给定两个或多个分组列(例如 player 和 team)的基础上,统计另一个分类列(例如 result)中每个唯一值的出现次数,并将这些唯一值作为新的列呈现在结果数据框中。

例如,我们有以下数据:

import pandas as pd

df = pd.DataFrame({'player':['A','A','B','B','C','D'],
                 'team':['tmX','tmX','tmX','tmX','tmY','tmY'],
                 'result':['hit','hit','hit','miss','miss','hit']})
print(df)

输出:

  player team result
0      A  tmX    hit
1      A  tmX    hit
2      B  tmX    hit
3      B  tmX   miss
4      C  tmY   miss
5      D  tmY    hit

我们期望得到的结果是:

  player team hit miss
0      A  tmX   2    0
1      B  tmX   1    1
2      C  tmY   0    1
3      D  tmY   1    0

直接使用 groupby() 并对结果列进行 count() 操作,虽然能得到每个分组的总计数,但无法将 result 列的唯一值(如 'hit', 'miss')展开为独立的列:

new_df = df.groupby(['player','team'])['result'].count().reset_index()
print(new_df)

输出:

  player team result
0      A  tmX      2
1      B  tmX      2
2      C  tmY      1
3      D  tmY      1

这与我们期望的宽格式输出不符,因为它只提供了每个 (player, team) 组合的总 result 计数,而不是按 result 类型分类的计数。传统的 pd.crosstab 通常适用于两个维度,而 df.pivot() 或 df.pivot_table() 在这种情况下可能需要更复杂的参数设置才能达到目标。

解决方案:groupby().size().unstack() 组合技

为了实现上述需求,Pandas 提供了一个强大且灵活的组合方法:groupby().size().unstack()。这个方法能够有效地将多层分组的计数结果转换为宽格式。

绘蛙AI修图
绘蛙AI修图

绘蛙平台AI修图工具,支持手脚修复、商品重绘、AI扩图、AI换色

下载

核心思想是:

  1. 首先,对所有相关的分组列和需要计数并展开的列进行分组。
  2. 然后,计算每个最小分组的大小(即计数)。
  3. 最后,将用于计数的分类列从索引中“解堆叠”到列中。

下面是实现我们期望结果的代码:

import pandas as pd

df = pd.DataFrame({'player':['A','A','B','B','C','D'],
                 'team':['tmX','tmX','tmX','tmX','tmY','tmY'],
                 'result':['hit','hit','hit','miss','miss','hit']})

# 解决方案代码
result_df = (
    df.groupby(['player', 'team', 'result']) # 1. 按所有相关列分组
      .size()                               # 2. 计算每个分组的大小(计数)
      .unstack(level='result', fill_value=0) # 3. 将 'result' 列从索引中解堆叠到列,缺失值填充0
      .reset_index()                        # 4. 将 'player' 和 'team' 从索引重置为列
)

print(result_df)

输出:

result player team  hit  miss
0           A  tmX    2     0
1           B  tmX    1     1
2           C  tmY    0     1
3           D  tmY    1     0

步骤详解

  1. df.groupby(['player', 'team', 'result']): 这一步创建了一个多层索引的分组对象。它会根据 player、team 和 result 的所有唯一组合来创建分组。例如,('A', 'tmX', 'hit') 会是一个分组,('B', 'tmX', 'miss') 是另一个分组。

  2. .size(): 对上一步创建的每个最小分组,.size() 方法会计算该分组中元素的数量。此时,df 会变成一个 Series,其索引是 MultiIndex,包含 player、team 和 result,值为对应的计数。 例如,它可能包含类似 (A, tmX, hit): 2 和 (B, tmX, miss): 1 这样的项。

  3. .unstack(level='result', fill_value=0): 这是实现宽格式的关键步骤。unstack() 方法用于将 Series 或 DataFrame 的某一层索引“解堆叠”到列中。

    • level='result':指定要解堆叠的索引层为 result。这意味着 result 索引中的每个唯一值('hit', 'miss')都将成为新的列名。
    • fill_value=0:在解堆叠过程中,如果某个 (player, team) 组合没有特定的 result 类型(例如,玩家A没有'miss'结果),则在该位置会产生 NaN。fill_value=0 会将这些 NaN 值替换为0,这对于计数结果是合理的。

    经过这一步,我们得到了一个 DataFrame,其索引是 (player, team),列是 hit 和 miss。

  4. .reset_index(): unstack() 操作后,player 和 team 仍然是 DataFrame 的索引。.reset_index() 将这些索引层转换回普通的列,使得最终结果是一个标准的 DataFrame,具有数字索引和所有数据列。

注意事项与扩展

  • level 参数的灵活性: unstack() 的 level 参数可以接受整数(表示索引的层级,从0开始)或字符串(表示索引的名称)。在多层索引中,使用名称通常更具可读性。
  • fill_value 的重要性: 对于计数场景,fill_value=0 是非常重要的,它能确保所有未发生的事件都被正确地表示为0,而不是缺失值。
  • 性能: 对于中等大小的数据集,这种方法通常非常高效。对于超大型数据集,可以考虑使用 Dask 或 PySpark 等分布式计算框架。
  • 与其他方法的比较:
    • pd.crosstab():主要用于两个分类变量的交叉制表,虽然也能实现类似功能,但当分组维度增多时,groupby().size().unstack() 显得更为通用和灵活。
    • df.pivot_table():pivot_table 也能实现类似功能,例如 df.pivot_table(index=['player', 'team'], columns='result', aggfunc='size', fill_value=0)。这种方法同样有效,并且在需要进行其他聚合操作(如求和、平均值)时更为强大。对于纯粹的计数并将结果展开,groupby().size().unstack() 往往更为简洁直观。

总结

groupby().size().unstack().reset_index() 组合是 Pandas 中处理多维度分类计数并以宽格式呈现结果的强大工具。它通过明确的分组、计数和解堆叠步骤,提供了一个清晰、高效且易于理解的解决方案,特别适用于需要将某个分类列的唯一值转换为新列的场景。掌握这一技巧将极大地提升您在 Pandas 中进行数据透视和汇总分析的能力。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

319

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

228

2023.10.07

Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

49

2025.12.04

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

192

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

248

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

205

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1435

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

609

2023.11.24

vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

26

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.1万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号