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

如何根据DataFrame中的模式变化删除重复行?

保留连续重复模式的首行(跳过跨模式重复)

问题场景

现有如下包含ID、日期和各类别百分比的DataFrame:

import pandas as pd
df = pd.DataFrame({"ID":["A","A","A","A","A","A","A"],
                   "DATE":["01-1990","03-1990","04-1990","05-1990","06-1990","07-1990",
                           "08-1990"],
                   "CLASS A":[30,30,0,0,0,30,30],
                   "CLASS B":[50,50,50,50,50,50,50],
                   "CLASS C":[20,20,50,50,50,20,20]})

原始数据输出:

ID     DATE  CLASS A  CLASS B  CLASS C
0  A  01-1990       30       50       20
1  A  03-1990       30       50       20
2  A  04-1990        0       50       50
3  A  05-1990        0       50       50
4  A  06-1990        0       50       50
5  A  07-1990       30       50       20
6  A  08-1990       30       50       20   

需求说明

需要基于ID、CLASS A、CLASS B、CLASS C列,仅删除连续重复组内的重复行并保留首行;对于跨模式的重复(比如本例中首尾的30/50/20模式),需保留新出现的该模式的首行。最终期望结果:

ID     DATE  CLASS A  CLASS B  CLASS C
0  A  01-1990       30       50       20
2  A  04-1990        0       50       50
5  A  07-1990       30       50       20

注意:直接使用df.drop_duplicates(subset=['ID','CLASS A','CLASS B','CLASS C'], keep='first')会删除索引5、6的行,无法满足需求。

解决方案

核心思路是识别连续的重复组,只保留每个组的第一行,以下是两种可行方法:

方法1:用shift()标记模式变化行

通过对比当前行与上一行的目标列是否一致,筛选出模式变化的行(包含第一行):

# 生成标记:当前行与上一行模式不一致则为True
mask = df[['ID','CLASS A','CLASS B','CLASS C']].ne(df[['ID','CLASS A','CLASS B','CLASS C']].shift()).any(axis=1)
# 筛选符合条件的行
result = df[mask]

方法2:用groupby结合连续组ID分组

先生成连续重复组的标识,再按组取首行:

# 生成连续组ID:模式变化时ID递增
group_id = (df[['ID','CLASS A','CLASS B','CLASS C']].ne(df[['ID','CLASS A','CLASS B','CLASS C']].shift()).any(axis=1)).cumsum()
# 按组ID分组,保留每组第一行
result = df.groupby(group_id).first().reset_index(drop=True)

两种方法均能得到期望结果,其中方法1更简洁高效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:40:24