如何快速移除Pandas DataFrame重复索引及保留首个非NaN值的重复行?
Pandas DataFrame去重问题解答
我来帮你搞定这两个Pandas去重问题,都是日常数据处理里很常见的场景:
1. 如何快速移除Pandas DataFrame中的重复索引?
要高效删掉重复索引,直接利用Pandas索引的duplicated()方法就好——它会生成一个布尔数组,标记出哪些索引是重复的(默认从第二个重复项开始标记为True)。我们只需要对这个数组取反,就能筛选出只含唯一索引的行:
import pandas as pd import numpy as np # 构造带重复索引的示例DataFrame df = pd.DataFrame({'value': [10, 20, 30, 40]}, index=['x', 'x', 'y', 'z']) # 移除重复索引,保留首次出现的行 df_cleaned = df[~df.index.duplicated()] # 用loc写法更直观,效果一样 # df_cleaned = df.loc[~df.index.duplicated()] print(df_cleaned)
这个方法是矢量化操作,没有循环,处理大型数据集速度也很快,是最推荐的方式。
2. 如何高效移除Pandas DataFrame中的重复行,且始终保留首个非NaN值?
看你提供的示例数据,核心需求应该是按重复的索引分组,每个分组里的每一列都保留第一个出现的非NaN值,同时去掉重复的行。这里用groupby结合自定义聚合函数就能完美实现:
首先先看你的原始数据:
import pandas as pd import numpy as np data = pd.DataFrame({'a': [np.nan,np.nan,2,2,3,3,5], 'b': [2,1,1,1,np.nan,2,1]}, index=[pd.Timestamp('2018-03-01'), pd.Timestamp('2018-03-02'), pd.Timestamp('2018-03-02'), pd.Timestamp('2018-03-02'), pd.Timestamp('2018-03-03'), pd.Timestamp('2018-03-03'), pd.Timestamp('2018-03-04')]) print(data)
输出如下:
a b2018-03-01 NaN 2.0
2018-03-02 NaN 1.0
2018-03-02 2.0 1.0
2018-03-02 2.0 1.0
2018-03-03 3.0 NaN
2018-03-03 3.0 2.0
2018-03-04 5.0 1.0
接下来是处理步骤:我们按索引分组,对每一列应用一个函数,取出第一个非NaN值(如果列里全是NaN就保留NaN):
# 自定义函数:提取序列中的第一个非NaN值 def get_first_non_nan(series): non_nan_values = series.dropna() return non_nan_values.iloc[0] if not non_nan_values.empty else np.nan # 按索引分组并聚合 cleaned_data = data.groupby(data.index).agg(get_first_non_nan) print(cleaned_data)
处理后的输出:
a b2018-03-01 NaN 2.0
2018-03-02 2.0 1.0
2018-03-03 3.0 2.0
2018-03-04 5.0 1.0
如果你想写得更简洁,也可以用bfill()(向后填充NaN)结合取每组第一行的方式,效果完全一致:
cleaned_data = data.groupby(data.index).apply(lambda x: x.bfill().iloc[0])
这个写法更短,效率也不错,适合大部分场景。
内容的提问来源于stack exchange,提问作者Snow bunting
相关产品推荐
相关产品推荐

