MSBS7102 Lecture 7 · R 迷你项目:达尔文实验与配对 t 检验

以达尔文玉米授粉实验为案例,走完 R 语言数据分析全流程:数据导入检查、清洗、宽表转长表、ggplot2 可视化,并对比独立样本与配对 t 检验的相反结论。

1. 本讲信息

  • 课程:MSBS7102 Foundations in Biomedical Data Science(生物医学数据科学基础)
  • 讲次:Lecture 7(Integrative mini-project — Introduction to R)
  • 日期:2026-10-23
  • 地点:HKJC-S1A & HKJC-S1B
  • 讲师:Dr. Ray Hsu(许裕正,Yu Cheng Hsu)
  • 主课件:Materials/mini-project.pdf(21 页,与 mini-project-worksheet.qmd 同源)
本讲是一次整合性的迷你项目(mini-project):不再零散地学语法,而是用一个真实历史数据集,完整走一遍"从原始数据到科学结论"的数据分析流程,并回答一个核心问题——为什么用 R 而不是 Excel 或 SPSS。

2. 学习目标

依据课件第 2 页(Learning goal):
  1. 能够根据一段实验描述,设计一个简单的分析流程(analysis pipeline);
  1. 在指导下运用 R 完成数据清洗,并执行一次配对比较(paired comparison);
  1. 理解统计检验"在问什么",而不是死记公式;
  1. (课堂补充)学会正确借助 AI 工具辅助编程,并识别其风险。

3. 核心内容

3.1 案例背景:达尔文的玉米实验

本案例改编自 Sheldon Ross 的教材《Introductory Statistics》,原始数据来自达尔文(Charles Darwin)1876 年出版的著作《The Effects of Cross and Self Fertilization in the Vegetable Kingdom》。
  • 研究假设(Hypothesis):异花授粉(cross-pollination)的后代植株会比自花授粉(self-pollination)的后代更强壮——这里以植株高度衡量。
  • 实验设计:16 对玉米(Zea mays),每对包含一株自花授粉植株与一株异花授粉植株;每一对种在同一个花盆(pot)中 ,全研究共 4 个花盆。同一盆中的两株植株共享完全相同的土壤、水分、养分与光照。
  • 数据结构:每行记录花盆编号(Pots)、对子编号(Pair)、异花授粉植株高度(Cross_fertilized_plant,单位英寸)与自花授粉植株高度(Self_fertilized_plant)。
达尔文玉米实验设计示意
达尔文玉米实验设计示意
课件 p3:达尔文玉米实验设计——同一盆中成对种植异花授粉与自花授粉植株,共 16 对、4 盆。这个"成对种植"的设计细节是全讲的伏笔:它决定了后面必须使用配对 t 检验 而非独立样本 t 检验。

3.2 数据科学工作流程:先规划,后动手

课件引用 Griffin 等 2018 年提出的生命科学数据最佳实践,给出数据生命周期(data lifecycle)框架:
阶段(Life Cycle Stage)
本模块中的例子
Collecting(收集)
读取数据(read the data)
Integrating(整合)
——(本例未涉及)
Processing(处理)
操作数据表(manipulating tables)
Analyzing(分析)
报告统计量(reporting statistics)
Publishing(发表)
生成报告与图表(generating report and figures)
数据生命周期图
数据生命周期图
课件 p5:Griffin 等(2018)提出的数据生命周期图。讲师强调两点(课堂录音):规划先行 ——在跑任何代码之前就把"处理—分析—可视化"的方案写出来;实验设计决定统计方法 ——看到"成对设计"就应预见到要用配对检验。
据此,本讲的项目路线图(Project Roadmap)为五步:
  1. 数据导入与检查(Data Import & Inspection):确保数据完整性;
  1. 数据处理(Data Manipulation):计算每对内的高度差,体现配对设计;
  1. 探索性数据分析(Exploratory Data Analysis, EDA):可视化配对结构与差异分布;
  1. 统计检验(Statistical test):提出假设并做统计推断;
  1. 结论与报告(Conclusion & Reporting):解读 p 值与均值差。

3.3 数据导入与检查

分析前的第一件事永远是检查数据 ,重点看三类问题:缺失值(missing values)、录入错误(typos and human errors)、数据结构(data structures)。讲师在课堂分享了一个反面经验:读博时拿到合作方"大牛"提供的数千条数据未加检查直接分析,结果大量缺失值导致结论全部不显著——数据出问题,责任在分析者而非数据提供者。
导入代码使用 tidyverse 包(一套 R 数据科学工具集):
检查发现:str(zea_mays) 显示数据应为 16 对(16 行),实际却有 17 行;anyNA(zea_mays) 返回 TRUE,说明存在缺失值。再用 filter(is.na(Self_fertilized_plant) | is.na(Cross_fertilized_plant)) 定位(| 是"或"运算符,单个竖线),发现最后一行是一行被误插进数据、整行皆 NA 的表头残留(Pot6、Pair 均为 NA)。

3.4 数据清洗:好代码与坏代码

删除缺失行有两种写法,课件把两者并列对比:
推荐写法——用函数表达意图:
不推荐写法——按行号硬编码(hard code):
硬编码不可取的原因(课件第 10 页 + 课堂演示):
  • 不稳健(not robust) :[-1,] 若被误执行两次,会从 17 行 → 16 行 → 15 行,删掉真实数据;drop_na() 重复执行结果不变(幂等)。
  • 可读性差 :函数名 drop_na() 本身说明了意图;两个月后回看 [-1,],很难记起当初为什么删这一行。
  • 对变动脆弱 :数据框增删行列后,索引会变,按位置写死的代码容易悄悄出错。
课堂还强调:不要回到 Excel 里手工删数据 。手工改动无法追溯、无法复现;所有操作都应写在代码里,使全过程可恢复、可验证。
随后计算配对差值(paired difference)——这是后续统计检验真正关心的"生物学信号":
mutate() 新建一列 diff.height(每对内"异花授粉高度 − 自花授粉高度")。课堂演示了手工抽查:23.5 − 17.375 = 6.125,与第一行结果一致,确认计算无误。

3.5 宽表、长表与 pivot_longer()

画图前必须先解决数据形状问题。课件定义:
  • 宽表(wide table) :一个观测占一列(本例每行同时含异花、自花两个观测);
  • 长表(long table) :一行一个观测。
ggplot2 假设一行 = 一个观测 ,宽表直接画图会表现异常。用 pivot_longer() 把宽表转长表:
三个参数的含义(课件第 15 页):
  • cols:指定哪些列是观测值(两列用 c() 合并);
  • names_to = "Type":原来的两个列名变成新列 Type 里的分类取值;
  • values_to = "Height":原单元格中的测量数值堆叠进新列 Height。
转换后每对玉米占两行(一行 Cross、一行 Self),16 对共 32 行。讲师提到这相当于 Excel 的数据透视表(pivot table);测序数据常以宽表存储,做图前尤其要注意转换。
宽表与长表
宽表与长表
课件 p14:宽表与长表的定义,以及本讲要绘制的目标图。

3.6 可视化:展示配对结构的散点连线图

关键点:group = Pair 告诉 ggplot 哪两行属于同一对,geom_line() 才能把每一对的两点连线;scale_x_discrete() / scale_y_continuous() 分别为离散、连续轴添加带单位的轴标签。图中多数连线从 Self 指向 Cross 方向上行,直观提示异花授粉植株更高。
配对散点连线图
配对散点连线图
课件 p16:ggplot2 生成的配对散点连线图及代码——以连线呈现每对植株两种授粉方式下的高度。

3.7 统计检验:错与对的对照

假设检验回顾(课件第 13 页) :假设检验(hypothesis test)问的是——如果真没有差异(无效应),当前数据中的模式有多"意外"?先设定怀疑性的零假设 与备择假设 ;小的 p 值含义是"在 下如此极端的结果并不常见",而不是"假设被证明了"。术语上只有"拒绝 (reject)"与"未能拒绝 (fail to reject)"。
为什么配对重要 :同一盆两株共享土壤、水分、光照——盆内环境是共同背景。在配对内比较可以消去这一共同环境(混杂因素,confounder);把 32 株当两独立组则忽略了它。
错误做法——独立样本 t 检验(Darwin 的做法) :把数据当成两组各 16 株的独立样本:
$
结果:Welch 两样本 t 检验,t = 1.406,df = 27.048,p = 0.086 。在 0.05 水平下未能拒绝 ——结论变成"两种授粉方式无差异"。
独立样本 t 检验输出
独立样本 t 检验输出
课件 p17:错误做法——独立样本 t 检验输出(p = 0.0855)。
正确做法——配对 t 检验(Ronald Fisher 的修正) :同盆植株共享养分与天气条件,违反独立样本假设;正确的做法是检验配对差值的均值 :
$
结果:t = 2.055,df = 15(16 对,自由度 = 16 − 1),p = 0.029 ,均值差 2.39 英寸——拒绝 ,支持"异花授粉植株更高"。两段代码仅 paired = TRUE/FALSE 一字之差,结论却完全相反。
配对 t 检验输出
配对 t 检验输出
课件 p18:正确做法——配对 t 检验输出(p = 0.0289)。

3.8 结果讨论与实验局限

  • 同一份数据、同一个问题,用错检验会得出相反的结论 (Darwin p = 0.086 未能拒绝;Fisher p = 0.029 拒绝)。
  • 讨论部分应结合领域知识(课堂录音):植株高度是多基因控制的性状,不能仅凭一次授粉实验断定"更强壮"。
  • 实验局限(课件第 19 页):基因型未完全控制(genotype control)、样本量有限(sample size)——增大样本量能否维持结论,本身就是值得写进讨论的问题。

3.9 结课建议(课件第 20 页)

分析层面:永远了解数据的来龙去脉(context)、理解研究问题、动手前先规划分析与处理流程——"先规划再执行,而不是先执行再规划"(课堂录音)。
编码层面:代码完整记录分析过程,使计算透明、可验证、易复现;为代码写清晰的注释与文档,保证两个月后仍能读懂。

5. 课前思考 / 自测

以下题目提炼自本 session 的练习材料(practice question 系列):
  1. (R 向量运算)R 中把长度为 4 的向量乘以单个数字 1.125 时会发生什么?如果把 fade_rates 的元素顺序打乱后再与 base_signals 相乘,R 按名称 还是按位置匹配?(答案:单个数字被"回收"(recycling)到等长;二元运算只按位置匹配,不看名称。)
  1. (数据类型)向量 c(CD4 = 12, CD8 = "SATURATED", CD19 = 35, CD56 = 4) 中,instrument_log[1] 是什么类型?还能做数值加法吗?(答案:一个字符值会迫使整个向量变成字符型,无法再做数值加法;R 的类型强制转换层级为 logical → integer → double → character。)
  1. (可视化)用 ggplot2 画散点图时,如何把 Titanic 数据中本为数值的 Pclass 当作分类变量上色?如何把图例标签改成"1st/2nd/3rd Class"?(答案:aes(color = as.factor(Pclass)),再用 scale_color_discrete(labels = ...) 修改标签。)
  1. (统计思维,本讲核心)同一份达尔文数据,paired = FALSE 得 p = 0.086、paired = TRUE 得 p = 0.029——实验设计中的哪个细节决定了该用哪一个?(答案:每对植株同盆种植、共享环境,属配对设计。)
  1. (编码规范)为什么 drop_na() 优于 zea_mays[-1,]?从稳健性与可读性两方面作答。

6. 参考材料

  • 主课件:Materials/mini-project.pdf(Integrative mini-project — Introduction to R,21 页)
  • 课件源文件:Materials/mini-project-worksheet.qmd
  • 练习材料:Materials/practice-question-r-notes.qmd、practice-question-r-worksheet.qmd(R 基础:向量回收、索引、类型转换);Materials/practice-question-gg-notes.qmd、practice-question-gg-notes_answers.qmd(ggplot2 练习:DEG 数据与 Titanic 数据)
  • 课件阅读清单(p21):Griffin PC 等 2018 "Best Practice Data Life Cycle Approaches for the Life Sciences"(F1000Research 6:1618);Ross SM 2017 Introductory Statistics(案例来源)
  • 课堂录音:Recordings/MSBS7102-1023-summary.md、MSBS7102-1023-transcript.md

7. 课堂要点补充(据课堂录音整理)

AI 辅助编程"生存指南" (讲师利用剩余时间加讲):
  • 报错是常态:报错只是 R 在告诉你"这样不行",不必恐慌;读懂、修复、从中学习。
  • 区分三类信息:message(提示,通常无害)、warning(警告,代码仍执行但需核查是否符合预期)、error(错误,代码无法执行)。常见 error:object not found(对象不存在)、could not find function(函数名拼错或未加载库)、unexpected symbol(语法错误,如漏逗号)。
  • 向 AI 提问要有策略:说清目标、上下文、已有代码与报错信息,而不是整段照贴;处理医学数据时尤其要给足背景。
  • 警惕 AI 幻觉(hallucination):讲师以自己使用 Gemini 的经历为例,AI 会编造不存在的函数,生成结果必须核对后再用。
  • 保护敏感数据(最重要) :不要把原始数据直接上传给 AI 服务;先去除个人信息或改用模拟数据。
作业一(Assignment 1)相关信息 :
  • 共 22 分:21 分为题目本身,1 分给代码风格与注释(可读性、缩进、描述性命名);代码需可执行且结果正确才能得满分。
  • 提交格式为 .qmd 或 .Rmd 文件(无需提交 HTML),讲师会实际运行代码评分;截止时间为 2026-11-11 23:59(录音总结);该作业为全课程唯一作业,占总成绩 22%;提交后务必确认状态不是"待提交"。
  • 讲师鼓励使用 AI 完成代码部分,但强调要从中学习——只复制粘贴就失去了这门课的意义。
其他课堂强调 :
  • "统计结论 + 领域知识"是贯穿全课的原则:只报告"我做了 t 检验"而无解读,不构成有效论证。
  • 讲师以自己博士经历说明"先规划"的价值:曾被导师要求把每种方法都试一遍,结果完全相同——事前有充分理由的分析计划可以避免这种浪费。
  • R 的价值在于把人从手算中解放出来(讲师提到其导师那一代考试需手算检验统计量),让分析者专注于设计、解读与呈现。
上一篇
PAED7902 Lecture 7 · 感染病的基因组学策略
下一篇
MSBS7101 Lecture 7 · 变异检测与注释(二):bcftools 与 VEP
Loading...