You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame多组分组的唯一标识符分配及性能优化问询

高效实现Pandas按分组批量分配唯一标识符

问题场景

给定Pandas DataFrame如下:

import pandas as pd
df = pd.DataFrame({'A':[1,2,3,4,6,3,7,3,2,11,13,10,1,5],'B':[1,1,1,2,2,2,2,3,3,3,3,3,4,4], 
                   'C':[1,1,1,1,1,1,1,2,2,2,2,2,3,3]})

需求是为B列的分组按从上到下的顺序,每两组分配一个唯一标识符(例如B=1、2对应D=1,B=3、4对应D=2)。

原实现方式通过循环遍历分组切片并逐次赋值,在7万行数据场景下效率极低,原代码如下:

b_unique_cnt = df['B'].nunique()
the_list = list(range(1, b_unique_cnt+1))
slice_size = 2
list_of_slices = zip(*(iter(the_list),) * slice_size)
counter = 1
df['D'] = -1
for i in list_of_slices:
    df.loc[df['B'].isin(i), 'D'] = counter
    counter = counter + 1

df.head(15)

原方法效率瓶颈分析

原方法通过循环生成分组切片,每次调用isin和loc修改DataFrame列值,这种操作会反复触发Pandas的索引查找与数据更新,在数据量较大时,多次的切片和赋值会带来显著的性能开销,导致处理速度缓慢。

高效优化方案

方案1:向量化操作(最优性能)

利用pd.factorize对B列按出现顺序生成编码,再通过整数除法批量生成分组标识符,全程无循环,完全向量化:

# 对B列按首次出现顺序生成连续编码(从0开始)
b_codes, _ = pd.factorize(df['B'], sort=False)
slice_size = 2
# 整数除法后加1,让标识符从1开始
df['D'] = (b_codes // slice_size) + 1

原理:pd.factorize会按B列元素第一次出现的顺序生成连续整数编码(如B=1→0、B=2→1、B=3→2、B=4→3),通过// slice_size将每2个编码归为一组,最后加1让标识符从1起始,完美匹配需求。

方案2:映射字典法(逻辑清晰)

先提取B列唯一值的出现顺序,创建映射字典后一次性完成赋值:

slice_size = 2
# 获取B列唯一值的出现顺序(保证从上到下)
b_unique_order = df['B'].unique()
# 构建B值到分组标识符的映射
group_map = {b_val: (idx // slice_size) + 1 for idx, b_val in enumerate(b_unique_order)}
# 批量映射生成D列
df['D'] = df['B'].map(group_map)

原理:先拿到B列唯一值的原始顺序,遍历每个值并根据其索引位置计算对应的分组号,最后用map方法一次性完成整列的映射赋值,避免循环操作。

验证结果

两种方案生成的D列结果一致:

0     1
1     1
2     1
3     1
4     1
5     1
6     1
7     2
8     2
9     2
10    2
11    2
12    2
13    2
Name: D, dtype: int64

内容的提问来源于stack exchange,提问作者Arjun Chaudhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:45:32