cover

走马

陈粒

concat和merge

concat和merge

concat 和merge#

先明确核心定位

  • pd.concat()物理拼接,把多个 DataFrame/Series 按「行 / 列方向」直接拼在一起,基于索引对齐,不做值的匹配;
  • pd.merge()逻辑关联,基于列值相等将两个 DataFrame 合并,类似 SQL 的 JOIN 操作,核心是「按值匹配」。

一、pd.concat ():轴向堆叠(行 / 列直接拼)#

核心逻辑#

把多个结构相似 / 相关的 DataFrame,按「行方向(新增行)」或「列方向(新增列)」拼接,只看索引是否匹配,不关心列值是否相等。简单说就是「把表格粘在一起」,不做数据筛选。

核心语法#

pd.concat(
objs, # 要合并的DataFrame/Series列表,如 [df1, df2]
axis=0, # 0=行拼接(默认),1=列拼接
ignore_index=False, # 是否重置索引(避免重复索引)
join="outer" # outer=保留所有列/行(默认),inner=只保留重叠的列/行
)

示例(基于员工数据)#

先准备基础数据:

import pandas as pd
import numpy as np
# 员工基础信息表1(张三、李四、王五)
df1 = pd.DataFrame({
"姓名": ["张三", "李四", "王五"],
"年龄": [20, 25, 22],
"城市": ["北京", "上海", "广州"]
}, index=["员工1", "员工2", "员工3"])
# 员工基础信息表2(赵六、钱七)
df2 = pd.DataFrame({
"姓名": ["赵六", "钱七"],
"年龄": [28, 30],
"城市": ["北京", "深圳"]
}, index=["员工4", "员工5"])
# 员工薪资表(和df1索引一致)
df3 = pd.DataFrame({
"薪资": [8000, 12000, 9500],
"绩效": ["良", "优", "中"]
}, index=["员工1", "员工2", "员工3"])

场景 1:行拼接(axis=0,新增行)#

把 df1 和 df2 的行拼在一起(补充新员工):

df_row_concat = pd.concat([df1, df2], axis=0)
print("行拼接结果(新增员工行):")
print(df_row_concat)

输出(保留原有索引,列名一致直接拼):

姓名 年龄 城市
员工1 张三 20 北京
员工2 李四 25 上海
员工3 王五 22 广州
员工4 赵六 28 北京
员工5 钱七 30 深圳

场景 2:列拼接(axis=1,新增列)#

把 df1 和 df3 的列拼在一起(给员工加薪资 / 绩效列):

df_col_concat = pd.concat([df1, df3], axis=1)
print("\n列拼接结果(新增薪资/绩效列):")
print(df_col_concat)

输出(按索引对齐,员工 1/2/3 的列拼在一起):

姓名 年龄 城市 薪资 绩效
员工1 张三 20 北京 8000 良
员工2 李四 25 上海 12000 优
员工3 王五 22 广州 9500 中

二、pd.merge ():按键关联(类似 SQL JOIN)#

核心逻辑#

基于列值相等(不是索引)将两个 DataFrame 合并,核心是「按指定列的值匹配行」,比如用「姓名」「员工 ID」把「基础信息表」和「薪资表」关联起来,完全对应 SQL 的 INNER/LEFT/RIGHT/OUTER JOIN。

核心语法#

pd.merge(
left, # 左表(比如基础信息表)
right, # 右表(比如薪资表)
on=None, # 关联的键列名(需在两个表中都存在,如"姓名")
left_on=None, # 左表的键列(两表键列名不同时用,如左表"姓名",右表"员工姓名")
right_on=None, # 右表的键列
how="inner", # 连接方式:inner(默认)/left/right/outer
indicator=False # 是否显示每行的合并来源
)

示例(基于员工数据)#

准备关联用的两张表(基础信息 + 薪资绩效):

# 左表:员工基础信息(包含王五,无钱七)
df_base = pd.DataFrame({
"姓名": ["张三", "李四", "王五", "赵六"],
"年龄": [20, 25, 22, 28],
"城市": ["北京", "上海", "广州", "北京"]
})
# 右表:员工薪资绩效(无王五,有钱七)
df_salary = pd.DataFrame({
"姓名": ["张三", "李四", "赵六", "钱七"],
"薪资": [8000, 12000, 15000, 18000],
"绩效": ["良", "优", "优", "中"]
})

场景 1:内连接(inner,默认)#

只保留「两张表中都有」的姓名(张三、李四、赵六):

df_inner = pd.merge(df_base, df_salary, on="姓名", how="inner")
print("内连接结果(仅保留共同姓名):")
print(df_inner)

输出:

姓名 年龄 城市 薪资 绩效
0 张三 20 北京 8000 良
1 李四 25 上海 12000 优
2 赵六 28 北京 15000 优

场景 2:左连接(left)#

保留「左表所有行」,右表无匹配则补 NaN(王五的薪资 / 绩效为 NaN):

df_left = pd.merge(df_base, df_salary, on="姓名", how="left")
print("\n左连接结果(保留所有基础表员工):")
print(df_left)

输出:

姓名 年龄 城市 薪资 绩效
0 张三 20 北京 8000.0 良
1 李四 25 上海 12000.0 优
2 王五 22 广州 NaN NaN
3 赵六 28 北京 15000.0 优

场景 3:外连接(outer)#

保留「两张表所有行」,无匹配则补 NaN(王五、钱七都保留):

df_outer = pd.merge(df_base, df_salary, on="姓名", how="outer")
print("\n外连接结果(保留所有员工):")
print(df_outer)

输出:

姓名 年龄 城市 薪资 绩效
0 张三 20.0 北京 8000.0 良
1 李四 25.0 上海 12000.0 优
2 王五 22.0 广州 NaN NaN
3 赵六 28.0 北京 15000.0 优
4 钱七 NaN NaN 18000.0 中

三、concat vs merge 核心对比表#

维度pd.concat()pd.merge()
核心逻辑轴向堆叠(行 / 列直接拼接)按键值匹配(类似 SQL JOIN)
对齐依据基于索引(行 / 列索引)基于列值(指定的键列)
轴方向支持 axis=0(行)/axis=1(列)仅按列方向合并(新增列)
列名要求行拼接:列名可不同(补 NaN);列拼接:无强制要求需指定键列(列名可不同,用 left_on/right_on)
适用场景1. 同结构 DF 的行拼接(新增员工行)2. 同索引 DF 的列拼接(新增薪资列)1. 关联不同表的相关数据(基础信息 + 薪资)2. 按列值筛选合并(只保留共同员工)
类似 SQL 操作UNION ALL(行拼接)/ 横向拼接(列)INNER/LEFT/RIGHT/OUTER JOIN

总结#

  1. 选 concat 的场景:你需要「简单拼接」数据(行 / 列直接粘),比如把多个同结构的员工表拼在一起、给同索引的员工表加列,核心是「不筛选,只堆叠」;
  2. 选 merge 的场景:你需要「按值关联」数据,比如用姓名 / 员工 ID 把基础信息和薪资表合并、只保留两张表都有的员工,核心是「按键匹配,可筛选」;
  3. 关键判断:合并时是否需要「按列值筛选匹配」—— 不需要就用 concat,需要就用 merge。

文章目录

✨️ 复制成功,转载请标注本文地址