自学教程 学编程从这里开始

Pandas 数据拼接

承接《Pandas 数据合并》,本篇聚焦 concat 拼接(纵向堆叠、横向对齐),区分拼接与 merge 关联,详解参数、内外连接、多层索引拼接、重复索引、拼接后的校验,配套实战和坑点,保持系列教程统一风格。
前置导入与示例数据

import pandas as pd
import numpy as np

df1 = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["张三", "李四", "王五"],
    "sales": [1000, 1200, 900]
})
df2 = pd.DataFrame({
    "id": [4, 5, 6],
    "name": ["赵六", "孙七", "周八"],
    "sales": [1500, 1100, 1300]
})
df3 = pd.DataFrame({
    "id": [1, 2, 3],
    "profit": [120, 180, 95]
})
print("df1:")
print(df1)
print("df2:")
print(df2)
print("df3:")
print(df3)

一、concat 基础说明

pd.concat() 是 Pandas 最核心的数据拼接函数,不依靠匹配键,依靠索引对齐。

  • axis=0:纵向拼接(上下堆叠,增加行),最常用
  • axis=1:横向拼接(左右并排,增加列)

重点区分:

  • concat:拼接,按索引对齐,类似 SQL UNION ALL
  • merge:关联,按指定字段匹配,类似 SQL JOIN

基础语法

pd.concat(
    objs,
    axis=0,
    join="outer",
    ignore_index=False,
    keys=None,
    levels=None,
    names=None,
    verify_integrity=False,
    sort=False
)

二、纵向拼接 axis=0(上下合并)

适合多张列结构一致的报表合并,比如每月报表、多批次导出数据。

# 纵向拼接两张销售表
df_stack = pd.concat([df1, df2], axis=0)
print(df_stack)

ignore_index 重置索引(高频必用)

两张表原始索引都是 0,1,2,拼接后索引重复,后续筛选容易出错。

df_stack = pd.concat([df1, df2], axis=0, ignore_index=True)
  • ignore_index=True:丢弃原来索引,生成从0开始连续新索引。

join 参数:纵向拼接的 join

纵向拼接时 join 控制列的对齐方式

  • join="outer"(默认):取所有列的并集,不存在的列填充 NaN
  • join="inner":只保留两边共同存在的列(列交集)
# 只保留共同列
df_stack_inner = pd.concat([df1, df2], axis=0, join="inner")

keys 参数:来源标记(非常实用)

拼接后新增外层索引,标记这条数据来自哪一张表,方便溯源

df_stack_key = pd.concat([df1, df2], axis=0, keys=["1月","2月"], names=["source"])
print(df_stack_key)
# 取1月数据
print(df_stack_key.loc["1月"])

三、横向拼接 axis=1(左右并排)

横向拼接完全依靠索引对齐,不是按 id 字段匹配!

只有索引相同的行才会对齐到同一行,索引不存在的位置填充 NaN。

df_col = pd.concat([df1, df3], axis=1)
print(df_col)

join 参数:横向拼接的 join

横向拼接控制行索引的交集/并集

  • join="outer":索引取并集,全部行保留(默认)
  • join="inner":索引取交集,只保留两边都存在的索引行
df_col_inner = pd.concat([df1, df3], axis=1, join="inner")

⚠️ 重大误区:
如果你想按 id 字段匹配,不要用 concat(axis=1),改用 pd.merge!

四、verify_integrity 校验索引唯一性

verify_integrity=True:开启索引唯一性检查,如果拼接后索引重复,直接抛出异常,防止脏数据。
适合对索引严格的场景,性能会有损耗。

# 索引重复就报错
pd.concat([df1, df2], axis=0, verify_integrity=True)

五、sort 参数:排序列

sort=True:自动对结果的列名进行字母排序,旧版本默认开启,新版默认 False。

pd.concat([df1, df2], axis=0, sort=True)

六、多表拼接(列表传多个DataFrame)

df_a = pd.DataFrame({"x":[1,2]})
df_b = pd.DataFrame({"x":[3,4]})
df_c = pd.DataFrame({"x":[5,6]})
df_all = pd.concat([df_a, df_b, df_c], axis=0, ignore_index=True)

七、append 废弃提醒

df.append() 在 Pandas 2.0 版本已经移除,不要继续使用,替换方案:

# 旧写法(失效)
# df1.append(df2)

# 新写法
pd.concat([df1, df2], axis=0, ignore_index=True)

八、concat 搭配场景

场景1:批量读取多个csv文件合并

import os
file_list = ["sale1.csv","sale2.csv"]
df_list = []
for f in file_list:
    tmp = pd.read_csv(f)
    df_list.append(tmp)
df_all = pd.concat(df_list, ignore_index=True)

场景2:横向拼接多个指标表(索引对齐)

df_idx1 = df1.set_index("id")
df_idx3 = df3.set_index("id")
res = pd.concat([df_idx1, df_idx3], axis=1)

九、concat 与 merge / join 对比

函数对齐依据方向类比
pd.concat(axis=0)索引上下堆叠UNION ALL
pd.concat(axis=1)索引左右并排索引横向对齐
pd.merge指定字段 on关联JOIN
df.join索引左右关联索引LEFT JOIN

十、高频坑清单

  1. axis=1 横向拼接误以为是按id匹配,实际是索引对齐,数据错位
  2. 纵向拼接忘记 ignore_index=True,索引重复,后续 loc、合并出错
  3. 两张表列名大小写、空格不一致,concat 后多出很多NaN列
  4. keys 生成多层索引,取值时容易忘记外层key
  5. 大表多次循环concat(低效):先放入列表,最后一次性concat
  6. 数据类型不一致拼接后自动转为object,后续计算报错
  7. join=”inner” 容易误删数据,生产环境优先 outer,事后再过滤

十一、综合实战模板

def concat_row(df_list):
    """纵向堆叠,同结构报表合并"""
    return pd.concat(df_list, axis=0, ignore_index=True)

def concat_col_by_index(df_list):
    """按索引横向拼接"""
    return pd.concat(df_list, axis=1, join="outer")

# 使用示例
df_stack = concat_row([df1, df2])
print(df_stack)

十二、速查表

需求写法
合并多张结构相同的表,上下堆叠concat(axis=0, ignore_index=True)
拼接时标记数据来源concat(…, keys=[“A”,”B”])
只保留共同列concat(…, join=”inner”)
按索引左右并排concat(axis=1)
按字段关联匹配pd.merge,不要用concat
标签:

0 条笔记