如何获取两个DataFrame中不匹配值的索引与列名?
最优实现方法
要高效找出两个结构一致的DataFrame中数值不匹配元素的索引与列名,直接利用Pandas的向量化操作即可,无需循环遍历,性能最优。
步骤与代码示例
首先构造示例中的DataFrame:
import pandas as pd # 构造df1 df1 = pd.DataFrame( {'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8], 'C': [9, 10, 11, 12]}, index=[1, 2, 3, 4] ) # 构造df2 df2 = pd.DataFrame( {'A': [1, 2, 44, 4], 'B': [44, 6, 7, 8], 'C': [9, 10, 11, 44]}, index=[1, 2, 3, 4] )
然后实现核心逻辑:
def find_non_matching(df_a, df_b): # 先校验两个DataFrame的结构是否一致(索引、列名) if not (df_a.index.equals(df_b.index) and df_a.columns.equals(df_b.columns)): raise ValueError("两个DataFrame的索引或列名不匹配,无法进行比较") # 生成不匹配位置的布尔矩阵,stack后筛选出True的项,提取索引转为列表 non_match = (df_a != df_b).stack() return list(non_match[non_match].index) # 调用函数并输出结果 result = find_non_matching(df1, df2) print(f"non matching values are indexed : {result}")
代码解释
df_a != df_b:向量化比较每个位置的元素,返回一个布尔值DataFrame,不匹配的位置为True。.stack():将列名转换为多层索引的第二层,把二维结构转为一维Series,此时每个元素的索引为(原行索引, 列名)。non_match[non_match]:筛选出所有值为True的项,即不匹配的位置。list(...):将多层索引转换为元组列表,符合需求的输出格式。
特殊情况说明
如果DataFrame中存在NaN值,因为NaN != NaN会返回True,若需要忽略NaN的差异,可以改用df.compare()方法:
# 处理含NaN的情况,忽略NaN之间的差异 def find_non_matching_with_nan(df_a, df_b): if not (df_a.index.equals(df_b.index) and df_a.columns.equals(df_b.columns)): raise ValueError("两个DataFrame的索引或列名不匹配,无法进行比较") # 使用compare方法获取不匹配的位置 compare_result = df_a.compare(df_b) # 提取索引和原始列名(compare返回的列带后缀,需拆分) return [(idx, col.split('_')[0]) for idx, col in compare_result.stack().index]
内容的提问来源于stack exchange,提问作者Khaled DELLAL
相关产品推荐
相关产品推荐

