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

Pandas merge合并后表头带_x后缀、KeyError问题排查

问题场景
  • 现有按月拆分的CSV源文件,每月对应7个结构完全一致的分片文件
  • 处理目标:先按月用concat拼接生成分月数据集,再基于唯一id字段合并各月数据集,生成JAN_COUNT、FEB_COUNT这类带月份标识的统计字段,最终汇总计算2019年全年各类型指标总和
  • 运行时出现两类异常:
    • 即使指定id为关联键,合并结果反复出现Unnamed、Unnamed_x、Unnamed_x.1这类异常列名
    • 汇总全年指标时触发KeyError,提示JAN_COUNT_CARGO字段不存在,实际字段被自动添加_x后缀变为JAN_COUNT_CARGO_x
核心问题排查

代码共存在5处直接导致异常的逻辑错误:

  • DataFrame操作未生效:set_index()、sort_values()都是非原地操作,会返回处理后的新DataFrame,未将返回值重新赋值给变量时,这两行代码实际不产生任何效果。
  • 文件匹配范围错误:合并年度数据时用*2019.csv匹配文件,会把脚本运行过程中生成的2019.csv本身也纳入待合并列表,等于反复把未完成的合并结果重新读入参与merge,直接导致列重复、结构混乱。
  • 列名冲突未提前处理:所有月度数据集除id外的列名完全一致,merge时pandas会自动给重复列名加_x/_y后缀区分,自然不会生成预期的带月份前缀的列名,还会触发后续字段找不到的KeyError。
  • CSV写入参数错误:to_csv()的index参数仅接受布尔值(控制是否将行索引导出到文件),传入列名字符串会被判定为True,导致无列名的索引列被写入CSV,下次读取时pandas会自动将这类无名列命名为Unnamed: 0,多次读写后就会出现一堆Unnamed_x类的异常列。
  • 列选择语法错误:按列筛选子集时直接传入列名列表即可,在列表前多写的冒号属于pandas切片语法错误,会导致列选择逻辑不符合预期。
修正后代码
print("Importing modules")
import os, glob
import pandas as pd
from functools import reduce
print('Modules imported... Setting variables')

opath = r'dir of csvs'
mlist = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
unique_gridid = 'id'
os.chdir(opath)

print('Variables set... Merging csv files into monthly datasets')
month_df_list = []
for m in mlist:
    print(f'Running merge for {m} collecting csv files...')
    csvlist = [i for i in glob.glob(f'{m}2019_G*.csv')]
    # 拼接当月7个分片文件
    month_csv = pd.concat([pd.read_csv(csv) for csv in csvlist])
    # 按唯一id去重,避免重复id导致merge时产生笛卡尔积
    month_csv = month_csv.drop_duplicates(subset=unique_gridid, keep='last')
    # 给非id列添加月份前缀,从根源避免merge时列名冲突
    month_csv = month_csv.rename(columns={
        col: f'{m}_{col}' for col in month_csv.columns if col != unique_gridid
    })
    month_df_list.append(month_csv)
    print(f'Saving {m}2019.csv')
    # 修正to_csv参数,不导出行索引
    month_csv.to_csv(f'{m}2019.csv', index=False)

print('Merging the monthly into yearly dataset...')
# 直接合并内存中的月度DataFrame,避免重复读写磁盘和错误匹配文件
ALL2019DF = reduce(
    lambda left,right: pd.merge(left, right, on=unique_gridid, how='outer'),
    month_df_list
)

clist = ALL2019DF.columns.values.tolist()
# 修正列选择语法,移除多余冒号
ALL2019DF['2019_CARGO_COUNT'] = ALL2019DF[[s for s in clist if "CARGO_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_CARGO_VDAYS'] = ALL2019DF[[s for s in clist if "CARGO_VDAYS" in s]].sum(axis=1)
ALL2019DF['2019_FISHING_COUNT'] = ALL2019DF[[s for s in clist if "FISHING_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_FISHING_VDAYS'] = ALL2019DF[[s for s in clist if "FISHING_VDAYS" in s]].sum(axis=1)
ALL2019DF['2019_OTHER_COUNT'] = ALL2019DF[[s for s in clist if "OTHER_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_OTHER_VDAYS'] = ALL2019DF[[s for s in clist if "OTHER_VDAYS" in s]].sum(axis=1)
ALL2019DF['2019_PASSENGER_COUNT'] = ALL2019DF[[s for s in clist if "PASSENGER_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_PASSENGER_VDAYS'] = ALL2019DF[[s for s in clist if "PASSENGER_VDAYS" in s]].sum(axis=1)
ALL2019DF['2019_TANKER_COUNT'] = ALL2019DF[[s for s in clist if "TANKER_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_TANKER_VDAYS'] = ALL2019DF[[s for s in clist if "TANKER_VDAYS" in s]].sum(axis=1)
ALL2019DF['2019_ALL_COUNT'] = ALL2019DF[[s for s in clist if "ALL_COUNT" in s]].sum(axis=1)
ALL2019DF['2019_ALL_VDAYS'] = ALL2019DF[[s for s in clist if "ALL_VDAYS" in s]].sum(axis=1)

print('Saving final 2019 csv with totals')
ALL2019DF.to_csv('2019.csv', index=False)
print('Done')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:39:38