导读:本期聚焦于Canve创作的《Python如何基于多列进行数据透视并统计唯一值个数?》,敬请观看详情。数据透视时想统计的不是行数而是唯一值的个数,这个需求看似简单,却让不少人卡在了aggfunc参数的写法上。pandas的pivot_table默认聚合方式是求均值,换成nunique之后还会遇到dropna、margins、去重口径等一系列细节问题。本文围绕Python数据透视中的多列唯一值计数展开,先讲透pivot_table配合nunique的基本用法,再对比groupby加nunique、crosstab等多种实现思路,最后针对结果不对、层级列处理、大数据量性能等常见坑给出对应的解决方案和完整代码示例。

做数据分析时,统计需求经常不是简单的求和或计数,而是"有多少个不重复的值"。比如一张订单表里,同一客户可能下了多笔订单,你想按地区和月份统计"活跃客户数",这本质上就是一个基于多列的数据透视加唯一值计数问题。pandas里实现这个需求的核心组合是pivot_table配合nunique,但实际用起来有不少细节需要留意,下面结合具体例子把整套思路讲清楚。

Python如何基于多列进行数据透视并统计唯一值个数?

一、pivot_table配合nunique的基础用法

先构造一份模拟订单数据,包含地区、月份、客户ID和订单金额四个字段。目标是按地区和月份两个维度,统计每个分组下不重复客户的数量。核心代码如下:

import pandas as pd

df = pd.DataFrame({
    'region': ['华东', '华东', '华北', '华北', '华东', '华北'],
    'month':  ['1月', '1月', '1月', '1月', '2月', '2月'],
    'customer': ['A', 'B', 'A', 'C', 'A', 'C'],
    'amount': [100, 200, 150, 300, 120, 80]
})

result = pd.pivot_table(
    df,
    index='region',
    columns='month',
    values='customer',
    aggfunc='nunique'
)
print(result)

这里的关键点在aggfunc='nunique'。如果不指定聚合方式,pivot_table默认会对数值列求均值,对非数值列直接报错,所以很多人第一次用values指定了客户ID这种字符串列时会碰到DataError。把聚合函数换成nunique后,pandas会对每个分组的customer列做去重再计数,得到的正是每个地区每个月的活跃客户数。

还有一个容易忽略的参数是dropna。pivot_table的dropna参数控制的是"是否丢弃整行全为NaN的分组结果",而nunique在计数时默认不会把NaN算进去。如果你的数据里customer列存在缺失值,想要明确排除或保留,建议在透视前先用df['customer'].isna()检查一下,必要时用fillna或者dropna做预处理,避免统计口径和预期不一致。

二、多列维度与多层索引的处理

实际业务中维度往往不止两个。比如按地区、渠道、月份三个维度透视,可以把index和columns写成列表形式,结果会自动生成多层索引:

result = pd.pivot_table(
    df,
    index=['region', 'channel'],
    columns='month',
    values='customer',
    aggfunc='nunique',
    margins=True,          # 追加汇总行/列
    margins_name='总计'
)
print(result)

# 把多层索引拉平,方便导出到Excel
flat = result.reset_index()
flat.columns = ['_'.join(col).strip('_') if isinstance(col, tuple) else col
                for col in flat.columns]
print(flat)

当index传入列表时,结果是多层行索引;如果columns也传列表,列方向也会变成多层列索引。这种结构在分析时很有用,但导出或与其他表合并时经常需要拉平。上面的reset_index加列名拼接是比较通用的处理方式。

margins=True可以自动追加行列汇总,但要注意汇总单元格的口径:margin列的唯一值计数是跨整个行方向去重的,而不是把各行数字简单相加。比如华东1月有客户A、B共2人,2月有A共1人,总计列算出来是2而不是3,因为A在两个月都出现了。这个行为在业务上是正确的,但如果拿透视结果直接做加减校验,很容易误以为算错了。

三、groupby加nunique:更灵活的替代方案

如果只需要长表形式的结果,不一定要做成宽表透视,用groupby往往更直接:

result = (df
    .groupby(['region', 'month'])['customer']
    .nunique()
    .reset_index(name='active_users'))
print(result)

groupby写法的好处是链式操作流畅,后续做筛选、排序、可视化都很方便,而且性能通常比pivot_table略好一些,因为省去了从长表转宽表的重排过程。两者的适用场景可以这样区分:需要直接看交叉表或导出报表时用pivot_table,需要把统计结果继续喂给下游分析流程时用groupby。

如果想同时统计多个指标,比如既要唯一客户数又要订单总金额,可以给agg传一个字典或命名聚合:

result = df.groupby(['region', 'month']).agg(
    active_users=('customer', 'nunique'),
    total_amount=('amount', 'sum')
).reset_index()
print(result)

四、常见坑与性能优化

第一个常见的坑是统计结果偏大。原因多半是数据里存在重复记录或者维度字段本身有空格、大小写不一致,比如"客户a"和"客户A"被当成两个人。建议透视前先做一次df['customer'] = df['customer'].str.strip()这类清洗,必要时统一大小写。

第二个坑是大数据量下的性能。nunique需要为每个分组维护一个哈希集合,当分组数达到百万级、基数又很高时,内存和耗时都会明显上升。这种情况下可以先做显式去重再计数,把去重和透视拆成两步:

dedup = df[['region', 'month', 'customer']].drop_duplicates()
result = pd.pivot_table(
    dedup,
    index='region',
    columns='month',
    values='customer',
    aggfunc='count'   # 去重后count等价于nunique,且更快
)
print(result)

先drop_duplicates再count的方式,计算量集中在一次去重上,后续的count只是简单计数,整体速度通常比直接nunique快不少。另外如果数据规模特别大,也可以考虑先对customer做类别编码(astype('category')),减少哈希计算时的字符串比较开销。

总结一下,基于多列做唯一值计数,pivot_table加nunique是最直接的方案,groupby加nunique更灵活适合长表输出,大数据量时用先去重再计数的思路优化性能。掌握这几种写法后,面对各种活跃用户、去重商品数之类的统计需求基本都能从容应对。

Python数据透视唯一值计数pandas pivot_table修改时间:2026-09-03 17:34:58

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260903/49707.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。