导读:本期聚焦于小伙伴创作的《Pandas中如何按org_id分组并聚合多列实现去重拼接?》,敬请观看详情。把同一org_id下的多列数据合并成一行,同时去掉重复值再拼接字符串,是数据处理里的常见需求。直接用groupby加字符串相加会把重复项保留下来,结果又长又乱。正确做法是在聚合函数里先转成集合去重,再用join拼起来。本文说明如何用agg配合自定义函数,对多个字段分别做去重拼接,并比较apply与agg在性能和写法上的差异,帮你写出清晰且高效的清洗代码。

在数据分析工作中,我们经常会遇到这样的原始表:同一机构编号org_id在多条记录里反复出现,而每一行都带着部门名称、负责人、标签等字段。为了让报表更紧凑,需要把相同org_id的记录压成一行,并且把多列里的取值去重后拼成字符串。Pandas提供了groupby机制,但默认聚合不会自动去重,如果直接求和或字符串相加,会出现大量重复文本。理解分组对象的内部结构以及agg函数的传参方式,是写好这段代码的核心。

Pandas中如何按org_id分组并聚合多列实现去重拼接?

基础实现:用groupby与agg完成单列去重拼接

最直观的思路是先按org_id分组,然后对目标列应用一个能把多个值变成去重字符串的函数。Python内置的set可以轻松去重,但集合是无序的,若希望结果稳定,可以排序后再拼接。在agg中传入匿名函数或命名函数都可以,Pandas会把每个分组里该列形成的Series传进去。

下面构造一份示例数据,包含org_id、dept和owner两列,其中同一机构存在重复部门与重复负责人。我们用自定义函数先转集合再去重拼接,避免传统写法里出现的abc,abc这类冗余。

import pandas as pd

data = {
    'org_id': [1, 1, 1, 2, 2, 3],
    'dept': ['研发', '研发', '市场', '财务', '财务', '人事'],
    'owner': ['张三', '张三', '李四', '王五', '赵六', '钱七']
}
df = pd.DataFrame(data)

def deduplicate_join(series):
    # 转成集合去重,再排序保证结果稳定,最后用逗号拼接
    unique_items = sorted(set(series.dropna().astype(str)))
    return ','.join(unique_items)

result = df.groupby('org_id').agg({
    'dept': deduplicate_join,
    'owner': deduplicate_join
}).reset_index()

print(result)

上面的代码会输出三行,org_id为1的机构部门被合并为“研发,市场”,负责人变为“张三,李四”。这种写法逻辑清晰,且能复用在任意文本列上。需要注意的是,如果原始字段含缺失值,dropna可以避免把字符串nan拼进去,否则结果里会出现尴尬的nan字样。

相比先groupby再用加号拼接,自定义去重函数虽然多写几行,但数据质量更好。尤其在标签类字段里,用户往往只关心出现过哪些类别,而不关心出现几次,这时候去重拼接就是刚需而非可选项。

多列差异化聚合:同一分组内混合统计与拼接

真实业务里,往往不是所有列都要去重拼接。比如金额列需要求和,次数需要计数,而名称类字段才需要去重拼接。groupby的agg允许对不同的列传不同的聚合逻辑,我们可以把numpy的sum、size与自己的去重函数混用,一次算出所有指标。

以下示例在前面数据基础上增加金额字段amount,并对org_id分组后同时计算总金额、部门去重拼接和负责人去重拼接。通过字典形式声明每列的处理函数,代码可读性很高,也方便后续维护时增减字段。

import pandas as pd

data = {
    'org_id': [1, 1, 1, 2, 2, 3],
    'dept': ['研发', '研发', '市场', '财务', '财务', '人事'],
    'owner': ['张三', '张三', '李四', '王五', '赵六', '钱七'],
    'amount': [100, 200, 150, 300, 50, 80]
}
df = pd.DataFrame(data)

def deduplicate_join(series):
    unique_items = sorted(set(series.dropna().astype(str)))
    return ','.join(unique_items)

result = df.groupby('org_id').agg(
    total_amount=('amount', 'sum'),
    dept_list=('dept', deduplicate_join),
    owner_list=('owner', deduplicate_join),
    record_count=('org_id', 'size')
).reset_index()

print(result)

这种命名聚合(named aggregation)从Pandas 0.25开始支持,它让输出列名直接在agg里定义,不必再写繁琐的rename。对于宽表清洗来说,能在一步之内把数值统计和文本去重拼接全部完成,显著减少中间变量。

如果某些列本身就可能包含逗号,那么用逗号拼接会产生歧义。此时可以改用其他分隔符,比如竖线|,或者干脆返回Python列表对象而不是字符串。返回列表时,后续导出Excel虽不如字符串直观,但在程序内部继续处理反而更方便,避免了再次拆分字符串的开销。

性能与替代方案:apply与agg的取舍

当数据量达到百万行级别,频繁调用Python层自定义函数会让groupby变慢,因为Pandas无法把set操作向量化。一种替代思路是用apply对整个分组做处理,在分组内部用更底层的方式拼装,但apply本质也是逐组Python循环,未必更快。真正提升速度的办法,是尽量先用drop_duplicates缩小数据,再分组拼接。

下面演示先对org_id和需要拼接的列做去重,再轻量聚合,这样进入自定义函数的行数大幅减少,在重复度高的日志型数据上效果明显。

import pandas as pd

data = {
    'org_id': [1, 1, 1, 2, 2, 3],
    'dept': ['研发', '研发', '市场', '财务', '财务', '人事'],
    'owner': ['张三', '张三', '李四', '王五', '赵六', '钱七']
}
df = pd.DataFrame(data)

# 先按分组键和拼接列去重,降低后续聚合体积
dedup = df.drop_duplicates(subset=['org_id', 'dept', 'owner'])

def join_col(series):
    return ','.join(sorted(series.astype(str)))

result = dedup.groupby('org_id').agg(
    dept_list=('dept', join_col),
    owner_list=('owner', join_col)
).reset_index()

print(result)

从工程角度看,如果去重拼接只是报表展示前的最后一步,数据规模又在万行内,直接用前面讲的agg加自定义函数就足够。若嵌入到每日跑批的ETL里且数据膨胀快,就要评估是否该在数据库侧用GROUP_CONCAT配合DISTINCT先处理,把重活交给更擅长的组件。

另外,Pandas的explode方法可以和去重拼接反向配合:当别人给你一份已拼接好的文本列时,你能用split加explode还原成多行,再做其他关联。掌握这对互逆操作,面对机构维度数据进出宽表场景就能游刃有余,不至于被格式转换卡住进度。

Pandasgroupbyagg修改时间:2026-08-15 20:46:29

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