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

花韻仙語
发布: 2025-10-03 12:05:10
原创
229人浏览过

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()。这个方法能够有效地将多层分组的计数结果转换为宽格式。

Natural Language Playlist
Natural Language Playlist

探索语言和音乐之间丰富而复杂的关系,并使用 Transformer 语言模型构建播放列表。

Natural Language Playlist 67
查看详情 Natural Language Playlist

核心思想是:

  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 中进行数据透视和汇总分析的能力。

以上就是Pandas 多列分组统计与结果透视:实现交叉计数表的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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