Python中如何高效统计一对多关系DataFrame的合同内产品序号
问题背景
现有存储客户编码、合同编号、对应产品信息的DataFrame,需新增count列,对每个合同下的产品按现有顺序从1开始编号。原有逐行for循环实现在50万行规模数据下运行耗时极长,需要优化。
低效原因
原有逐行遍历+df.at逐单元格赋值的写法,完全在Python层执行循环,每次单元格读写都伴随索引校验、类型匹配的额外开销,没有利用pandas底层C实现的矢量化运算能力,性能极差。
高效实现方案
全程使用pandas原生矢量化接口,50万行数据处理耗时通常在100毫秒以内,代码如下:
注意:运行前请确认DataFrame已按
contract_number排序,同合同的行是连续排列的,和样例数据顺序一致。
# 按合同编号分组,生成组内从0开始的累计序号,+1后得到从1开始的计数 df['count'] = df.groupby('contract_number').cumcount() + 1
如果数据还未排序,先执行排序再计数即可:
# 按合同编号排序,重置索引保证行号连续 df = df.sort_values(by='contract_number', ignore_index=True) df['count'] = df.groupby('contract_number').cumcount() + 1
效果验证
运行代码后得到的结果和目标效果完全一致:
| client_code | contract_number | product | count |
|---|---|---|---|
| AAAA | 1000 | Water | 1 |
| AAAA | 1000 | Soda | 2 |
| AAAA | 1000 | Food | 3 |
| BACD | 1001 | Water | 1 |
| BACD | 1001 | Soda | 2 |
| DAMR | 1002 | Food | 1 |
性能对比
- 原有for循环实现:50万行数据耗时约1小时
- 矢量化groupby实现:同规模数据耗时<0.2秒,性能提升超过10000倍
内容的提问来源于stack exchange,提问作者Radu Iordache
相关产品推荐
相关产品推荐

