说明

pd.concat() 用于将多个 Series、DataFrame 或 Panel 沿指定轴向拼接,不会按键对齐,而是简单地堆叠,是处理同结构数据的核心工具。

语法

pd.concat(
    objs,                # 要拼接的对象序列(list / dict / Series / DataFrame)
    *,
    axis=0,              # 拼接轴向:0=行,1=列
    join='outer',        # 索引对齐方式:'outer' 或 'inner'
    ignore_index=False,  # 是否忽略原索引重新生成 0..n-1
    keys=None,           # 分组键,生成 MultiIndex
    levels=None,         # 与 keys 配合的分组层次
    names=None,          # 生成的 MultiIndex 的层级名称
    verify_integrity=False,  # 检查结果索引是否唯一
    sort=False,          # 对齐时是否对非连接轴索引排序
    copy=None,           # 是否复制底层数据(None 使用 Copy-on-Write 默认)
)

参数说明

参数说明示例
objs要拼接的对象序列,可以是 list、dict[df1, df2]、{'a': df1, 'b': df2}
axis拼接轴向:0=行(垂直),1=列(水平)axis=0、axis=1
join非拼接轴的索引对齐方式:'outer' 并集,'inner' 交集join='inner'
ignore_index是否忽略原索引,生成新的 0..n-1 整数索引ignore_index=True
keys分组键,用于创建 MultiIndex 分层keys=['x', 'y']
levels指定分层索引的具体层级(需与 keys 配合)levels=[['a', 'b']]
names分层索引的层级名称names=['group', 'row']
verify_integrity若结果为 True,检查索引是否有重复并抛出异常verify_integrity=True
sort非连接轴对齐时是否排序sort=True
copy是否复制底层数据copy=False

基础拼接

import pandas as pd
 
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
 
# 默认 axis=0,垂直拼接(增加行)
print(pd.concat([df1, df2]))
#    A  B
# 0  1  3
# 1  2  4
# 0  5  7
# 1  6  8
 
# axis=1,水平拼接(增加列)
print(pd.concat([df1, df2], axis=1))
#    A  B  A  B
# 0  1  3  5  7
# 1  2  4  6  8

join 参数:索引对齐

说明

合并时非拼接轴的索引会进行对齐,join 控制取并集还是交集。

df3 = pd.DataFrame({'A': [1, 2]}, index=[0, 1])
df4 = pd.DataFrame({'B': [3, 4]}, index=[1, 2])
 
# outer(默认):索引并集,缺失处为 NaN
print(pd.concat([df3, df4], axis=1))
#      A    B
# 0  1.0  NaN
# 1  2.0  3.0
# 2  NaN  4.0
 
# inner:索引交集
print(pd.concat([df3, df4], axis=1, join='inner'))
#    A  B
# 1  2  3

ignore_index

说明

拼接后重新生成 0..n-1 的整数索引,避免重复索引问题。

print(pd.concat([df1, df2], ignore_index=True))
#    A  B
# 0  1  3
# 1  2  4
# 2  5  7
# 3  6  8

keys 与 MultiIndex

说明

通过 keys 参数为新拼接的数据添加上层分组标签,生成 MultiIndex,便于事后区分数据来源。

print(pd.concat([df1, df2], keys=['first', 'second']))
#            A  B
# first  0  1  3
#        1  2  4
# second 0  5  7
#        1  6  8
 
# 指定层级名称
print(pd.concat([df1, df2], keys=['g1', 'g2'], names=['group', 'row']))
#                A  B
# group row
# g1    0     1  3
#       1     2  4
# g2    0     5  7
#       1     6  8
 
# 使用 dict 时自动使用键名
print(pd.concat({'one': df1, 'two': df2}, names=['source', 'index']))

拼接 Series

s1 = pd.Series([1, 2], name='s1')
s2 = pd.Series([3, 4], name='s2')
 
# 垂直拼接成 Series
print(pd.concat([s1, s2]))
# 0    1
# 1    2
# 0    3
# 1    4
 
# 水平拼接成 DataFrame
print(pd.concat([s1, s2], axis=1))
#    s1  s2
# 0   1   3
# 1   2   4

verify_integrity 与 sort

# 检查索引唯一性
try:
    pd.concat([df1, df2], verify_integrity=True)
except ValueError as e:
    print(e)  # Indexes have overlapping values: Index([0, 1], dtype='int64')
 
# sort:对非连接轴索引排序
df5 = pd.DataFrame({'B': [1]}, index=[2])
df6 = pd.DataFrame({'A': [2]}, index=[1])
print(pd.concat([df5, df6], axis=1, sort=True))
#    B    A
# 1 NaN  2.0
# 2 1.0  NaN

性能提示

大量拼接注意

  • pd.concat() 在循环中反复调用效率较低,建议改为先收集列表再一次性 concat。
  • copy=False 配合 Copy-on-Write 可避免不必要的数据复制,但需注意视图与副本问题,参考 视图与副本。

🔗 相关链接