使用Pandas Query对比CSV时首尾为0的字符串误判不一致问题
问题
读取两个CSV文件并以字符串类型对比数据,通过Pandas的merge关联后用query输出不匹配行时,发现首尾带0的字符串(如0214008000000)明明完全相同,却被判定为不匹配。
数据示例
csv_1
id, id_2, name, unit, dep, sales, code, others 1, 22, apple, 100, 243837463, 89.90, 0214008000000, 88899 2, 23, orange, 403, 111839281, 10.10, 7474836251038465, 80000
csv_2
id, id_2, name, unit, department, sales, special_code, others 1, 22, apple, 100, 243837463, 89.900, 0214008000000, 88899 2, 23, orange, 403, 111839281, 10.10, 7474836251038465, 80300 3, 24, banana, 909, 784635281, 30.17, 6241325251038465, 80000
代码实现
import pandas as pd df1 = pd.read_csv(csv_1, header=0, dtype=str, na_filter=False) df2 = pd.read_csv(csv_2, header=0, dtype=str, na_filter=False) df1.reset_index(drop=True, inplace=True) df2.reset_index(drop=True, inplace=True) df1 = df1.applymap(str.strip) # 去除首尾空格 df2 = df2.applymap(str.strip) # 去除首尾空格 # ....其他数据处理 dfx = pd.merge(df1, df2, left_on=['id', 'id_2'], right_on=['id', 'id_2'], suffixes=['_data1', '_data2']) print(dfx.query('name_data1 != name_data2')) print(dfx.query('unit_data1 != unit_data2')) print(dfx.query('dep != department')) print(dfx.query('master_jan != jan_dh')) print(dfx.query('sales_data1 != sales_data2')) print(dfx.query('code != special_code')) print(dfx.query('others_data1 != others_data2'))
异常现象
执行后,code字段的0214008000000在两个文件中内容完全一致,却被query('code != special_code')判定为不匹配并输出。
排查与解决
以下是几种可能的原因及对应解决方法:
隐藏不可见字符
字符串表面看起来相同,但可能包含空格、制表符、换行符或其他不可见ASCII字符。虽然代码中用了str.strip(),但strip()仅去除首尾的空白字符,若字符中间夹杂不可见字符,仍会导致不匹配。
解决:使用工具清除所有非打印字符,示例代码:import unicodedata def clean_str(s): # 移除所有非打印字符 return ''.join(c for c in s if unicodedata.category(c)[0] != 'C') df1 = df1.applymap(clean_str) df2 = df2.applymap(clean_str)字符串编码差异
两个文件的字符串编码不一致(如一个是UTF-8带BOM,一个是纯UTF-8),导致读取后字符串底层字节不同。
解决:读取CSV时指定统一编码,同时处理BOM:df1 = pd.read_csv(csv_1, header=0, dtype=str, na_filter=False, encoding='utf-8-sig') df2 = pd.read_csv(csv_2, header=0, dtype=str, na_filter=False, encoding='utf-8-sig')Pandas的dtype转换遗漏
虽然指定了dtype=str,但部分长数字串可能被Pandas自动转换为数值类型,导致字符串对比时类型不匹配。
解决:验证字段类型,确保目标字段均为字符串:print(df1['code'].dtype) print(df2['special_code'].dtype) # 若类型不符,强制转换 df1['code'] = df1['code'].astype(str) df2['special_code'] = df2['special_code'].astype(str)merge后的字段名混淆
检查merge后的dfx中,code和special_code是否确实是来自两个文件的对应字段,避免因字段名重复或处理错误导致对比对象错误。
解决:查看列名确认字段来源,若命名混乱可提前重命名:print(dfx.columns) # 重命名对齐字段 df2.rename(columns={'special_code': 'code'}, inplace=True) dfx = pd.merge(df1, df2, left_on=['id', 'id_2'], right_on=['id', 'id_2'], suffixes=['_data1', '_data2']) # 此时对比应为code_data1 != code_data2
内容的提问来源于stack exchange,提问作者Jasmine
相关产品推荐
相关产品推荐

