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

Pandas多DataFrame使用concat(axis=0)纵向拼接失效问题

问题根因

拼接错位、横向偏移和ignore_index=True参数无关,核心原因是执行pd.concat拼接时,所有待拼接的DataFrame都未设置列名,pandas默认用数字索引作为列匹配依据,只要不同服务器返回的查询结果列顺序、列数量存在微小差异,就会按数字列名对齐,最终出现横向错位。
查看原有代码的执行顺序可以明确问题:

  1. 先执行df = pd.DataFrame(cursor.fetchall())生成无列名的DataFrame,直接就和全局变量alldf做concat拼接
  2. 拼接完成后才单独给当前单台服务器的df设置df.columns = field_names,这步操作完全不会影响已经拼接到alldf中的内容,且全局alldf自始至终没有设置过统一列名。
    此外原有代码还存在重复导入、变量名拼写错误、资源未正常释放的问题,会进一步提升异常出现概率。
修复方案

调整代码执行顺序,先给当前查询返回的df设置统一列名,再执行拼接操作,同时统一所有df的列结构,从根源避免列错位。

修复后的核心代码段

将executor函数的逻辑替换为以下内容即可:

def executor(QUERY):
    alldf = None
    
    for type,info in locs.items():
        fileChecker(type)

        for ip,locName in info.items():
            cnx = None
            try:
                cnx = mysql.connector.connect(user=usr, password=passwd,host=ip, database=db)

                if cnx.is_connected():
                    print("Connection Succesfull to {}".format(locName))
                    logwriter(type,ip,locName,True)

                    location = cnx.cursor(buffered=True)
                    location.execute("SELECT loccod FROM docparameters d limit 1")
                    loc = location.fetchone()[0]
                    location.close()
        
                    
                    cursor = cnx.cursor()
                    cursor.execute(QUERY)
                    raw_data = cursor.fetchall()
                    # 先提取列名、给当前df设置列名,再做后续操作
                    field_names = [ i[0] for i in  cursor.description]
                    df = pd.DataFrame(raw_data, columns=field_names)
                    cursor.close()

                    # 单台服务器结果单独落盘
                    xlswriter = pd.ExcelWriter('{}/{}.xlsx'.format(type,loc),engine='openpyxl')
                    if not df.empty:
                        # 拼接前保证当前df列名、列顺序和全局alldf完全一致
                        if alldf is not None:
                            # 兜底对齐:补全缺失列、调整列顺序和全局df完全匹配
                            df = df.reindex(columns=alldf.columns)
                            alldf = pd.concat([alldf,df],ignore_index=True,axis=0)
                        else:
                            # 第一台服务器的结果作为全局df的列基准
                            alldf = df
                      
                        df.to_excel(xlswriter,index=False)
                        xlswriter.save()
                    xlswriter.close()
   
            except mysql.connector.Error as err:
                if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
                    print("Something wrong with your username or password")
                elif err.errno == errorcode.ER_BAD_DB_ERROR:
                    print("DATABASE does not exist")
                else:
                    print(err)
                    print("Connection Failed to %s"%(locName))
                    logwriter(type,ip,locName,False)
            finally:
                # 统一在finally块关闭连接,避免资源泄漏
                if cnx and cnx.is_connected():
                    cnx.close()

    return alldf

额外避坑点

  • 原有代码里写的index=false存在问题,pandas接收的布尔值是首字母大写的False,直接写false会触发命名错误,需要改为index=False
  • openpyxl引擎不支持.xls后缀文件,建议把输出后缀统一改成.xlsx,避免保存时报错
  • 所有游标、文件写入对象、数据库连接建议放到finally块统一关闭,避免连接泄漏导致后续服务器连接失败
  • 拼接前增加df.reindex(columns=alldf.columns)是兜底逻辑,哪怕某台服务器返回的列顺序错乱、缺失个别列,也会自动对齐列顺序、给缺失列填充空值,彻底避免横向错位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:54:37