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

Pandas按行去重指定列重复值:保留首次或x6列值

处理百万行Pandas DataFrame指定列的行内重复值问题

需求说明

现有一个超过700万行的Pandas DataFrame,需要对指定列(x3、x4、x5、x6、x7、v、y、ay、by、cy、gy、uap、ubp)按行去重:删除数值重复项,仅保留首次出现的副本(多数行首次出现在x6列,若x6有重复值则优先保留x6的副本)。

原始DataFrame

import pandas as pd
import numpy as np

data = {'date': ['2023-02-22', '2023-02-21', '2023-02-23'],
        'x1': ['descx1a', 'descx1b', 'descx1c'],
        'x2': ['ALSFNHF950', 'KLUGUIF615', np.nan],
        'x3': [np.nan, np.nan, 24319.4],
        'x4': [np.nan, np.nan, 24334.15],
        'x5': [np.nan, np.nan, 24040.11],
        'x6': [np.nan, 75.33, 24220.34],
        'x7': [np.nan, np.nan, np.nan],
        'v': [np.nan, np.nan, np.nan],
        'y': [404.29, np.nan, np.nan],
        'ay': [np.nan, np.nan, np.nan],
        'by': [np.nan, np.nan, np.nan],
        'cy': [np.nan, np.nan, np.nan],
        'gy': [np.nan, np.nan, np.nan],
        'uap': [404.29, 75.33, np.nan],
        'ubp': [404.29, 75.33, np.nan],
        'sf': [np.nan, 2.0, np.nan]}

df = pd.DataFrame(data)

期望输出

import pandas as pd
import numpy as np

data = {'date': ['2023-02-22', '2023-02-21', '2023-02-23'],
        'x1': ['descx1a', 'descx1b', 'descx1c'],
        'x2': ['ALSFNHF950', 'KLUGUIF615', np.nan],
        'x3': [np.nan, np.nan, 24319.4],
        'x4': [np.nan, np.nan, 24334.15],
        'x5': [np.nan, np.nan, 24040.11],
        'x6': [np.nan, 75.33, 24220.34],
        'x7': [np.nan, np.nan, np.nan],
        'v': [np.nan, np.nan, np.nan],
        'y': [404.29, np.nan, np.nan],
        'ay': [np.nan, np.nan, np.nan],
        'by': [np.nan, np.nan, np.nan],
        'cy': [np.nan, np.nan, np.nan],
        'gy': [np.nan, np.nan, np.nan],
        'uap': [np.nan, np.nan, np.nan],
        'ubp': [np.nan, np.nan, np.nan],
        'sf': [np.nan, 2.0, np.nan]}

expected_df = pd.DataFrame(data)

错误尝试代码

原代码错误地使用了列方向的duplicated()方法,该方法用于判断行与行之间的重复,而非行内列与列的重复:

check = ['x3', 'x4', 'x5', 'x6', 'x7', 'v', 'y', 'ay', 'by', 'cy', 'gy', 'uap', 'ubp']

df[check] = df[check].where(~df[check].duplicated(), np.nan)

正确实现方法

针对700万行的大数据量,推荐使用矢量化的长格式转换方法,避免逐行apply的低效:

import pandas as pd
import numpy as np

# 定义需要处理的列列表
check = ['x3', 'x4', 'x5', 'x6', 'x7', 'v', 'y', 'ay', 'by', 'cy', 'gy', 'uap', 'ubp']

# 1. 将指定列转换为长格式,保留行索引
melted = df[check].reset_index().melt(id_vars='index', var_name='col', value_name='val').dropna(subset=['val'])

# 2. 定义列的顺序优先级,用于判断首次出现的位置
col_order = {col: idx for idx, col in enumerate(check)}
melted['order'] = melted['col'].map(col_order)

# 3. 按行索引和数值分组,找到每个数值在该行中最早出现的列(优先级最高的列)
first_col = melted.groupby(['index', 'val'])['order'].idxmin()
first_col = melted.loc[first_col, ['index', 'val', 'col']].rename(columns={'col': 'first_col'})

# 4. 合并回长格式数据,标记需要保留的单元格
melted = melted.merge(first_col, on=['index', 'val'])
melted['value'] = np.where(melted['col'] == melted['first_col'], melted['val'], np.nan)

# 5. 转换回宽格式,匹配原列顺序
result = melted.pivot(index='index', columns='col', values='value').reindex(columns=check)

# 6. 将处理后的数据赋值回原DataFrame
df[check] = result

代码说明

  1. 长格式转换:把宽表转成每行对应一个单元格的长表,方便按行+数值分组处理。
  2. 列优先级定义:根据check列表的顺序,给每个列分配优先级,确保x6在列表中靠前的话会优先被保留(符合需求中“多数行首次出现在x6”的场景)。
  3. 分组找首次出现列:对每一行的每个数值,找到它最早出现的列,只保留该列的数值,其他列的重复值设为NaN。
  4. 转回宽格式:将处理后的长表还原为原宽表结构,覆盖原DataFrame的指定列。

这种方法全程使用Pandas的矢量化操作,效率远高于逐行apply,适合处理百万级别的大数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:18:33