第十四章:数据合并:merge / join(Pandas)

第十四章:数据合并:merge / join(Pandas)

    • [14.1 本章你将学会什么](#14.1 本章你将学会什么)
    • [14.2 一句话先讲清:merge / join / concat 区别是什么?](#14.2 一句话先讲清:merge / join / concat 区别是什么?)
    • [14.3 连接类型(inner/left/right/outer)到底差在哪?](#14.3 连接类型(inner/left/right/outer)到底差在哪?)
    • [14.4 准备两张"科研风格"的示例表](#14.4 准备两张“科研风格”的示例表)
    • [14.5 最常用:pd.merge(明确写清 keys)](#14.5 最常用:pd.merge(明确写清 keys))
      • [14.5.1 inner:只保留两边都出现的 sid](#14.5.1 inner:只保留两边都出现的 sid)
      • [14.5.2 left:以左表为准(科研里最常见)](#14.5.2 left:以左表为准(科研里最常见))
      • [14.5.3 outer:保留并集,用于"找差异、做核对"](#14.5.3 outer:保留并集,用于“找差异、做核对”)
    • [14.6 多键合并:不止 sid,一个键不够怎么办?](#14.6 多键合并:不止 sid,一个键不够怎么办?)
    • [14.7 合并前必须检查的 3 件事(不做就等着翻车)](#14.7 合并前必须检查的 3 件事(不做就等着翻车))
      • [14.7.1 键的 dtype 是否一致(最隐蔽的坑)](#14.7.1 键的 dtype 是否一致(最隐蔽的坑))
      • [14.7.2 键是否唯一:1:1、1:m、m:m 你得心里有数](#14.7.2 键是否唯一:1:1、1:m、m:m 你得心里有数)
      • [14.7.3 用 validate 强制约束合并关系(强烈推荐)](#14.7.3 用 validate 强制约束合并关系(强烈推荐))
    • [14.8 列名冲突:suffixes 一次解决](#14.8 列名冲突:suffixes 一次解决)
    • [14.9 join:当索引就是键时,用它更顺手](#14.9 join:当索引就是键时,用它更顺手)
    • [14.10 研究型 Checklist:合并质量自检清单](#14.10 研究型 Checklist:合并质量自检清单)
    • [14.11 本章练习(建议你真跑一遍)](#14.11 本章练习(建议你真跑一遍))
      • [练习 1:用 outer + indicator 找出不一致 sid](#练习 1:用 outer + indicator 找出不一致 sid)
      • [练习 2:用 validate 保证 1:m 合并](#练习 2:用 validate 保证 1:m 合并)
      • [练习 3:处理列名冲突](#练习 3:处理列名冲突)
    • [14.12 小结:你应该带走的"工程化结论"](#14.12 小结:你应该带走的“工程化结论”)
    • 下一篇:

在真实科研数据里,"清洗"只是前菜;真正让数据变得可分析的,往往是把来自不同来源的表 对齐并合并

这一章我们用一套可复现的小例子,把 merge / join / concat 讲透,并把最常踩的坑一次性踩完、填平。


14.1 本章你将学会什么

  • 理解 主键(key)参照完整性:为什么"能合并"不代表"合并对"
  • 掌握 pd.merge()4 种连接inner / left / right / outer
  • 处理真实场景的常见问题:重复键、列名冲突、缺失键、类型不一致
  • 学会用 indicator=True 做合并质量检查(科研数据必备)

14.2 一句话先讲清:merge / join / concat 区别是什么?

  • concat上下拼接或左右拼接(按轴叠起来),不负责"对齐键"
  • merge:按某个(些)键把两张表 像 SQL JOIN 一样对齐后合并
  • join:更偏向 按索引(index)合并 (当然也能指定 on,但本质是 merge 的语法糖)

记住一句话:
科研数据合并,优先考虑 merge;只有当索引就是键时,再用 join。


14.3 连接类型(inner/left/right/outer)到底差在哪?

你可以把合并想象成"以键为准,决定保留哪些行"。
outer
保留并集 keys
right
保留右表全部 keys + 匹配到的左表
left
保留左表全部 keys + 匹配到的右表
inner
只保留交集 keys
左表 keys
右表 keys


14.4 准备两张"科研风格"的示例表

我们用一个常见场景:

  • 表 A:样本基本信息(subject-level)
  • 表 B:测量指标(measurement-level)
python 复制代码
import pandas as pd

df_subject = pd.DataFrame({
    "sid": [101, 102, 103, 104],
    "group": ["control", "control", "treatment", "treatment"],
    "age": [23, 25, 22, 24]
})

df_score = pd.DataFrame({
    "sid": [101, 102, 102, 105],
    "score": [88, 91, 95, 77],
    "timepoint": ["T1", "T1", "T2", "T1"]
})

df_subject, df_score

注意:df_score 里有:

  • sid=102 重复键(同一被试多时间点)
  • sid=105 在 A 表不存在(右表多出来的键)

14.5 最常用:pd.merge(明确写清 keys)

14.5.1 inner:只保留两边都出现的 sid

python 复制代码
inner = pd.merge(df_subject, df_score, on="sid", how="inner")
inner

适用场景:

  • 你只关心"有完整信息且有测量记录"的样本
  • 做回归、ANOVA 时常用(但要警惕样本被你默默删掉)

14.5.2 left:以左表为准(科研里最常见)

python 复制代码
left = pd.merge(df_subject, df_score, on="sid", how="left")
left

适用场景:

  • 你要保留全部被试,只是某些被试缺测(score 为 NaN)
  • 后续再决定缺失处理策略(删除 / 插补 / 分析缺失机制)

14.5.3 outer:保留并集,用于"找差异、做核对"

python 复制代码
outer = pd.merge(df_subject, df_score, on="sid", how="outer", indicator=True)
outer

这句 indicator=True 非常关键:它会生成一列 _merge,告诉你每行来自哪里:

  • both:两边都有
  • left_only:只在左表
  • right_only:只在右表

科研数据合并我建议形成习惯:
先 outer + indicator 做核对,再决定用 left/inner 进入正式分析。


14.6 多键合并:不止 sid,一个键不够怎么办?

典型例子:同一被试多个时间点,多次测量要严格对齐。

python 复制代码
df_score2 = pd.DataFrame({
    "sid": [101, 102, 102, 103],
    "timepoint": ["T1", "T1", "T2", "T1"],
    "score": [88, 91, 95, 90]
})

df_demo = pd.DataFrame({
    "sid": [101, 102, 102, 103],
    "timepoint": ["T1", "T1", "T2", "T1"],
    "sleep_hours": [7.0, 6.5, 6.0, 7.5]
})

multi = pd.merge(df_score2, df_demo, on=["sid", "timepoint"], how="inner")
multi

当你的测量表是"长表"(long format)时,多键合并非常常见。


14.7 合并前必须检查的 3 件事(不做就等着翻车)

14.7.1 键的 dtype 是否一致(最隐蔽的坑)

python 复制代码
df_subject["sid"].dtype, df_score["sid"].dtype

如果一边是 int,另一边是 str,合并会出现"看似没报错、但全是 NaN"的假象。

统一类型:

python 复制代码
df_subject["sid"] = df_subject["sid"].astype(str)
df_score["sid"] = df_score["sid"].astype(str)

14.7.2 键是否唯一:1:1、1:m、m:m 你得心里有数

python 复制代码
df_subject["sid"].is_unique, df_score["sid"].is_unique
  • df_subject 是 1(subject-level)
  • df_score 是 m(多测量)

于是合并的结果是 1:m,行数会增加,这是正常的。

但如果两边都是重复键,就会变成 m:m,行数会指数级膨胀(灾难级)。


14.7.3 用 validate 强制约束合并关系(强烈推荐)

python 复制代码
pd.merge(df_subject, df_score, on="sid", how="left", validate="one_to_many")

可选:

  • "one_to_one"
  • "one_to_many"
  • "many_to_one"
  • "many_to_many"(不建议,除非你真的确认)

这对科研数据特别重要:它让错误尽早暴露,而不是让你在统计结果阶段才发现"样本数不对"。


14.8 列名冲突:suffixes 一次解决

当左右表有同名列(比如都叫 agedatesource),合并后会自动加后缀。你也可以自己定义:

python 复制代码
df_a = pd.DataFrame({"sid":[1,2], "age":[20,21]})
df_b = pd.DataFrame({"sid":[1,2], "age":[200,210]})

pd.merge(df_a, df_b, on="sid", suffixes=("_subj", "_measure"))

14.9 join:当索引就是键时,用它更顺手

python 复制代码
left = df_subject.set_index("sid")
right = df_score.set_index("sid")

joined = left.join(right, how="left")
joined

经验结论:

  • 你的键在列里:用 merge
  • 你的键在 index 里:用 join

14.10 研究型 Checklist:合并质量自检清单

合并完成后,至少回答这 5 个问题:

  1. 合并前后行数是否符合预期?(特别是 1:m、m:m)
  2. _mergeleft_only/right_only 是否在合理范围?
  3. key 的缺失值是否被引入?(是否要先 dropna 还是保留)
  4. 是否出现意外重复?(同一 sid×timepoint 是否变多)
  5. 是否存在 dtype 被无意改变?(如日期字符串变对象)

14.11 本章练习(建议你真跑一遍)

练习 1:用 outer + indicator 找出不一致 sid

  • 输出只在 df_subject 的 sid
  • 输出只在 df_score 的 sid

练习 2:用 validate 保证 1:m 合并

  • merge 在你不小心把左表也变成重复键时立刻报错

练习 3:处理列名冲突

  • 人为制造同名列,使用 suffixes 输出一个可读的表

14.12 小结:你应该带走的"工程化结论"

  • 科研合并的第一原则:先核对,再合并(outer + indicator)
  • 合并的第二原则:把关系说清楚(validate)
  • 合并的第三原则:键的 dtype 要一致、键的唯一性要明确

下一篇:

《第十五章:可视化入门:Matplotlib 做出像样的图》

相关推荐
不会用AI的老炮19 小时前
【AI coding 智能体设计系列-05】上下文治理:清空压缩摘要与预算控制
人工智能·ai·ai编程
速易达网络19 小时前
AI工具全景:从概念到产业的深度变革
人工智能
点云SLAM19 小时前
Algebraic 英文单词学习
人工智能·英文单词学习·雅思备考·代数形式的·代数的 / 与代数相关的·algebraic
狮子座明仔19 小时前
DISCOG:知识图谱+LLM双引擎驱动的法律电子取证系统
人工智能·深度学习·知识图谱
Ydwlcloud19 小时前
2026年1月云服务器优惠活动全解析:聪明选云的新策略
大数据·服务器·人工智能·云计算
AI Echoes19 小时前
LangChain 语义文档分割器与其他文档分割器的使用
大数据·人工智能·python·langchain·agent
易天ETU19 小时前
2026年光模块市场分析与预见
大数据·运维·网络·人工智能·光模块·光通信
橙露19 小时前
视觉检测光源全解析:种类、优缺点与场景选型指南
人工智能·计算机视觉·视觉检测
橙露19 小时前
深度解析:马达脉冲本质、PLC控制逻辑及视觉检测应用全指南
人工智能·计算机视觉·视觉检测
Blossom.11819 小时前
基于多智能体协作的自动化数据分析系统实践:从单点工具到全流程智能
运维·人工智能·分布式·智能手机·自动化·prompt·边缘计算