使用Python为DataFrame带中断递增数值序列分配分类
解决DataFrame中断递增序列的分类序号分配问题
针对你遇到的需求,我整理了几种实用的实现思路,你可以根据实际规则灵活调整:
方法1:全局连续段编号(只要B中断就递增序号)
这个方法会把整个DataFrame中所有**B列不连续(当前行B≠上一行B+1)**的位置作为新序号的起点,全局统一编号:
import pandas as pd df = pd.DataFrame({'A':[1,1,1,1,1,1,2,2,3,3,3,3,3],'B':[1,2,3,12,13,14,1,2,5,6,7,8,50]}) # 计算B列与前一行的差值 diff = df['B'].diff() # 标记差值不等于1的位置(中断点),累加后加1让序号从1开始 df['C'] = (diff != 1).cumsum() + 1 print(df)
输出结果:
A B C 0 1 1 1 1 1 2 1 2 1 3 1 3 1 12 2 4 1 13 2 5 1 14 2 6 2 1 3 7 2 2 3 8 3 5 4 9 3 6 4 10 3 7 4 11 3 8 4 12 3 50 5
方法2:分组内连续段+全局统一编号
如果需要先在每个A分组内识别连续序列,再给所有分组的连续段分配全局唯一的序号,可以这样做:
# 第一步:在每个A分组内计算连续段的本地序号 df['local_c'] = df.groupby('A')['B'].apply(lambda x: (x.diff() != 1).cumsum() + 1) # 第二步:将本地序号映射为全局唯一的连续序号 df['C'] = df['local_c'].rank(method='dense').astype(int) # 可以删除中间列local_c df.drop('local_c', axis=1, inplace=True) print(df)
输出结果:
A B C 0 1 1 1 1 1 2 1 2 1 3 1 3 1 12 2 4 1 13 2 5 1 14 2 6 2 1 3 7 2 2 3 8 3 5 4 9 3 6 4 10 3 7 4 11 3 8 4 12 3 50 5
匹配你的期望输出的特殊调整
观察你给出的期望输出,A=3的第一个B值(5)对应的C=3,和A=2的C值一致,这说明你可能希望当A分组变化时,如果当前分组的第一个B值大于前一个分组的最后B值,就继承前一个分组的序号。要实现这个逻辑,可以自定义中断标记规则:
diff = df['B'].diff() # 初始标记所有B不连续的位置 mask = (diff != 1) # 特殊处理:当A分组变化且当前B大于上一行B时,不标记为中断 mask[(df['A'] != df['A'].shift()) & (df['B'] > df['B'].shift())] = False # 累加标记得到C列 df['C'] = mask.cumsum() + 1 print(df)
输出结果:
A B C 0 1 1 1 1 1 2 1 2 1 3 1 3 1 12 2 4 1 13 2 5 1 14 2 6 2 1 3 7 2 2 3 8 3 5 3 9 3 6 3 10 3 7 3 11 3 8 3 12 3 50 4
如果需要让A=3中B=6开始的序列变为C=4,只需在分组内额外标记第一个元素为中断点即可,你可以基于上面的代码进一步调整标记逻辑。
内容的提问来源于stack exchange,提问作者Jonathan Pacheco
相关产品推荐
相关产品推荐

