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

高效移除Pandas DataFrame中重复的子DataFrame

高效移除Pandas DataFrame中重复的子DataFrame

嘿,针对你遇到的这个要高效移除重复子DataFrame的问题,我这里有个性能拉满的解决方案,比你原来的循环方法快太多了,尤其适合百万级别的大数据量!

先回顾下你的示例数据和需求:
你有这样一个DataFrame:

import pandas as pd

df_dupl = pd.DataFrame({
    'EVENT_TIME': ['00:01', '00:01', '00:01', '00:03', '00:03', '00:03', '00:06', '00:06', '00:06', '00:08', '00:08', '00:10', '00:10', '00:11', '00:11', '00:13', '00:13', '00:13'],
    'UNIQUE_ID': [123, 123, 123, 125, 125, 125, 123, 123, 123, 127, 127, 123, 123, 123, 123, 123, 123, 123],
    'Value1': ['A', 'B', 'A', 'A', 'B', 'A', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'C', 'B', 'A', 'B', 'A'],
    'Value2': [0.3, 0.2, 0.2, 0.1, 1.3, 0.2, 0.3, 0.2, 0.2, 0.1, 1.3, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2, 0.2]
})

你的核心需求是:按UNIQUE_ID分组后,只保留和上一个同ID的EVENT_TIME子DataFrame不重复的那些子DataFrame——比如00:06的123子DataFrame和00:01的完全一致,所以要删掉;但00:13的虽然也和00:01一致,但中间隔了00:10、00:11的子DataFrame,所以要保留。


高效解决方案(无NaN场景)

这个方法用Pandas的分组、移位和向量化操作,完全避免了循环,性能提升非常明显:

# 定义需要比较的数值列
value_cols = ['Value1', 'Value2']
# 给每个(UNIQUE_ID, EVENT_TIME)组内的行分配序号,用来对齐前后组的行做比较
enums = df_dupl.groupby(['UNIQUE_ID', 'EVENT_TIME']).cumcount()
# 分组键:UNIQUE_ID + 组内序号
groups = ['UNIQUE_ID', enums]

# 计算每个(UNIQUE_ID, EVENT_TIME)组的行数大小
sizes = df_dupl.groupby(['UNIQUE_ID', 'EVENT_TIME']).transform('size')

# 判断当前子DataFrame是否和上一个同UNIQUE_ID的子DataFrame完全重复
dup = (
    # 检查每一行的value_cols是否和上一个同组序号的行的值相等
    df_dupl.groupby(groups)[value_cols].shift().eq(df_dupl[value_cols]).all(axis=1)
    # 确保组内所有行都满足上述条件(即整个子DataFrame完全重复)
    .groupby(['UNIQUE_ID', 'EVENT_TIME']).transform('all')
    # 同时当前组的大小要和上一个同UNIQUE_ID的组大小一致
    & sizes.groupby(df_dupl['UNIQUE_ID']).diff().eq(0)
)

# 过滤掉重复的子DataFrame,保留原数据顺序
df_result = df_dupl[~dup].sort_values(['UNIQUE_ID', 'EVENT_TIME'], kind='stable').reset_index(drop=True)

处理含NaN的场景

如果你的数据里有NaN,并且需要把NaN视为相等的话,只需要修改重复判断的逻辑即可:

value_cols = ['Value1', 'Value2']
enums = df_dupl.groupby(['UNIQUE_ID', 'EVENT_TIME']).cumcount()
groups = ['UNIQUE_ID', enums]
sizes = df_dupl.groupby(['UNIQUE_ID', 'EVENT_TIME']).transform('size')

# 修改判断逻辑,把NaN相等的情况也纳入判断
dup = (
    (
        df_dupl.groupby(groups)[value_cols].shift().eq(df_dupl[value_cols])
        # 新增:前后行都是NaN的情况也视为相等
        | (df_dupl.groupby(groups)[value_cols].shift().isna() & df_dupl[value_cols].isna())
    ).all(axis=1)
    .groupby(['UNIQUE_ID', 'EVENT_TIME']).transform('all')
    & sizes.groupby(df_dupl['UNIQUE_ID']).diff().eq(0)
)

df_result = df_dupl[~dup].sort_values(['UNIQUE_ID', 'EVENT_TIME'], kind='stable').reset_index(drop=True)

性能对比

我们针对不同数据量测试了几种方案的耗时,结果如下(单位:毫秒):

方法1000行10000行100000行
你的原方法5565410未测试
其他方案696-12404560-10100未测试
上述最优方案11.334.1318

可以看到,这个最优方案的性能碾压其他方法,即使处理10万行也只需要300多毫秒,完全能hold住百万级别的数据。

备注:内容来源于stack exchange,提问作者user23503493

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 07:48:03