Pandas中对比DataFrame并拼接差异值时索引越界的解决咨询
解决CSV文件按组合键对比列差异时的索引越界问题
问题描述
有两个列名相同的CSV文件(df1和df2),需以column1与column2的组合为匹配键,对比其余列的差异:
- 差异值用
|拼接 - 无差异则显示
. - 仅在单个文件中存在的行保留原值
运行现有代码时,因GHI行仅存在于df1中,出现index 1 is out of bounds for axis 0 with size 1错误,需解决该问题。
文件示例
df1
column1 column2 column3 column4 ABC 100 020 030 DEF 200 040 050 GHI 300 001 002
df2
column1 column2 column3 column4 ABC 100 060 070 DEF 200 040 090
期望输出
column1 column2 column3 column4 ABC 100 020 | 060 030 | 070 DEF 200 . 050 | 090 GHI 300 001 002
现有代码
import pandas as pd import numpy as np df = pd.concat([df1,df2], sort=False) df.set_index(['column1', 'column2'], inplace=True) df = df.replace(np.nan, '', regex=True) def report_diff(x): print(x) return '.' if x[0] == x[1] else '{} | {}'.format(*x) changes = df.groupby(level=['column1', 'column2']).agg(report_diff) display(changes)
错误原因
现有代码的report_diff函数默认每个分组都包含2个元素(分别来自df1和df2),但仅在单个文件存在的行(如GHI)分组后仅包含1个元素,此时访问x[1]会触发索引越界错误。
解决方案
修改report_diff函数,先判断分组的元素数量,分别处理单文件行和双文件行的情况:
修改后的完整代码
import pandas as pd import numpy as np # 示例数据读取(实际场景替换为pd.read_csv) df1 = pd.DataFrame({ 'column1': ['ABC', 'DEF', 'GHI'], 'column2': [100, 200, 300], 'column3': ['020', '040', '001'], 'column4': ['030', '050', '002'] }) df2 = pd.DataFrame({ 'column1': ['ABC', 'DEF'], 'column2': [100, 200], 'column3': ['060', '040'], 'column4': ['070', '090'] }) df = pd.concat([df1, df2], sort=False) df.set_index(['column1', 'column2'], inplace=True) def report_diff(x): # 处理仅在单个文件存在的行,直接返回原值 if len(x) == 1: return x.iloc[0] # 处理两个文件都存在的行,对比值生成结果 val1, val2 = x.iloc[0], x.iloc[1] return '.' if val1 == val2 else f'{val1} | {val2}' # 按组合键分组并应用差异处理函数 changes = df.groupby(level=['column1', 'column2']).agg(report_diff) # 重置索引恢复column1和column2为普通列 changes = changes.reset_index() # 打印结果 print(changes.to_string(index=False))
关键修改点
- 移除无效的空值替换:单文件行的分组不会产生空值,无需替换
np.nan为空白字符串 - 增加分组长度判断:
- 当分组长度为1时,直接返回唯一的元素(对应仅在一个文件存在的行)
- 当分组长度为2时,提取两个值进行对比,按规则返回
.或拼接字符串
- 重置索引:将作为分组键的
column1和column2从索引恢复为普通列,与期望输出格式一致
运行结果
column1 column2 column3 column4 ABC 100 020 | 060 030 | 070 DEF 200 . 050 | 090 GHI 300 001 002
内容的提问来源于stack exchange,提问作者soosa
相关产品推荐
相关产品推荐

