R Markdown与可重复研究

R语言在生物信息学中的应用

王诗翔 副教授
中南大学生物医学信息系

2025-01-01

课程大纲

本讲内容

  1. 什么是R Markdown
  2. Markdown基本语法
  3. R Markdown文档结构
  1. 代码块选项
  2. Quarto:下一代工作流
  3. 可重复性研究最佳实践

第1部分:什么是R Markdown?

1.1 传统科研流程的痛点

❌ 传统方式

  • Excel + Word + PPT 分离
  • 数据更新后手动重绘图表
  • 代码和文档不同步
  • 难以复现分析过程
  • 合作者看不懂分析步骤

✅ R Markdown方式

  • 代码 + 文档 一体化
  • 数据更新自动刷新图表
  • 一处修改,全局更新
  • 完全可重复的分析
  • 生成HTML / PDF / Word多格式

💡 R Markdown实现了文学编程(Literate Programming)的理念

1.2 R Markdown的核心价值

.Rmd文件 → knitr执行R代码 → Markdown → pandoc渲染 → HTML/PDF/Word
     ↑______________________________________________|
               (数据更新后重新knit即可)

三大核心优势

  1. 动态报告 — 数据变化,报告自动更新
  2. 可重复性 — 他人可完全复现分析过程
  3. 多格式输出 — 一份源码,生成多种格式

参考:Yihui Xie 的 R Markdown: The Definitive Guide
https://bookdown.org/yihui/rmarkdown/

第2部分:Markdown基本语法

2.1 什么是Markdown?

Markdown是轻量级标记语言,用纯文本格式编写,一键转换为格式化文档

设计哲学

“让格式语法尽可能可读” — John Gruber(Markdown创始人)

优势

  • ✅ 纯文本,版本控制友好(Git追踪变化)
  • ✅ 易读易写,专注内容
  • ✅ 一键转换为 HTML / PDF / Word / 幻灯片

2.2 标题与文本格式

# 一级标题(H1)
## 二级标题(H2)
### 三级标题(H3)

**粗体文字**   *斜体文字*   ~~删除线~~

> 这是一段引用文字(blockquote)

---  (水平分隔线)

粗体文字 斜体文字 删除线

这是一段引用文字(blockquote)

2.3 列表与链接

- 无序列表项目一
  - 子项目(缩进2个空格)
- 无序列表项目二

1. 有序列表第一条
2. 有序列表第二条

[R官网](https://www.r-project.org/)
![图片描述](https://hadley.nz/hadley.jpg)
  • 无序列表项目一
    • 子项目(缩进2个空格)
  • 无序列表项目二

R官网

图片描述

2.4 表格语法

| 基因 | 表达量 | 显著性 | 调控方向 |
|------|--------|--------|---------|
| TP53 | 12.5 | *** | 上调 |
| KRAS | 8.3  | *   | 上调 |
| BRCA1 | 3.1 | ns  | 下调 |
基因 表达量 显著性 调控方向
TP53 12.5 *** 上调
KRAS 8.3 * 上调
BRCA1 3.1 ns 下调

2.5 代码与公式

行内代码与代码块

使用 `filter()` 函数筛选数据

```r
# R代码块(语法高亮)
library(dplyr)
data |> filter(age > 50) |> select(id, age)
```

这里只会标记代码,不会像 RMarkdown 里代码可以执行

2.5 代码与公式

LaTeX数学公式

行内公式:$BMI = \frac{weight}{height^2}$

独立公式:
$$
\bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_i,\quad
s = \sqrt{\frac{\sum(x_i - \bar{x})^2}{n-1}}
$$

第3部分:R Markdown文档结构

3.1 R Markdown的组成

在RStudio中创建:File → New File → R Markdown

---
title: "TP53基因表达分析报告"
author: "王诗翔"
date: "2025-03-16"
output: html_document
---

## 简介

TP53是重要的**肿瘤抑制基因**...

## 数据分析

```{r load-data}
expr_data <- read.csv("tp53_expression.csv")
summary(expr_data)
```

根据上述统计摘要,数据包含 `r nrow(expr_data)` 个样本。

三大组成: 1. YAML元数据---包围的头部) 2. Markdown文本(叙述性内容) 3. R代码块(以```{r} 开始)

3.2 YAML元数据配置

---
title: "RNA-seq差异表达分析"
subtitle: "基于DESeq2的肿瘤vs正常分析"
author: "王诗翔"
date: "2026-03-19"   # 自动插入今天的日期
output: 
  html_document:
    toc: true            # 显示目录
    toc_float: true      # 浮动目录
    code_folding: hide   # 代码默认折叠
    theme: cosmo         # 文档主题
    fig_width: 8         # 图宽(英寸)
    fig_height: 6        # 图高(英寸)
    df_print: paged      # 分页显示数据框
---

3.3 代码块基本语法

R Markdown传统语法

```{r chunk-name, echo=TRUE, eval=TRUE, fig.width=8}
# 代码块名称唯一,方便导航和引用
library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point()
```

3.3 代码块基本语法

常用选项速查

选项 说明 默认值
echo 是否显示代码 TRUE
eval 是否执行代码 TRUE
results 输出处理方式 'markup'
warning 是否显示警告 TRUE
message 是否显示消息 TRUE
fig.width 图宽(英寸) 7
fig.height 图高(英寸) 5
fig.cap 图片标题 NULL

3.4 代码块演示

① 只显示结果(隐藏代码)

```{r, echo=FALSE}
summary(cars)
```
     speed           dist       
 Min.   : 4.0   Min.   :  2.00  
 1st Qu.:12.0   1st Qu.: 26.00  
 Median :15.0   Median : 36.00  
 Mean   :15.4   Mean   : 42.98  
 3rd Qu.:19.0   3rd Qu.: 56.00  
 Max.   :25.0   Max.   :120.00  

3.4 代码块演示

② 只显示代码(不执行)

```{r, eval=FALSE}
BiocManager::install("DESeq2")  # 安装包(不执行)
```

③ 隐藏一切(后台运行)

```{r setup, include=FALSE}
library(ggplot2)
library(dplyr)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE)
```

3.5 内联代码(Inline Code)

在文本中嵌入R计算结果,实现动态更新

本次分析共 `r nrow(cars)` 个样本,
平均速度 `r round(mean(cars$speed), 1)` mph,
中位刹车距离 `r median(cars$dist)` 英尺。

本次分析共 50 个样本, 平均速度 15.4 mph, 中位刹车距离 36 英尺。

生信应用场景

  • 正文中自动更新样本量、P值
  • 确保正文与表格一致(避免手动填错)
  • 比较结果描述随数据自动调整

3.6 图表输出

# 创建演示数据
set.seed(42)
df <- data.frame(
  group      = rep(c("Tumor", "Normal"), each = 20),
  expression = c(rnorm(20, 12, 2), rnorm(20, 7, 1.5))
)

boxplot(expression ~ group, data = df,
        main = "TP53基因表达",
        ylab = "表达量(log2 FPKM)",
        col  = c("#E74C3C", "#3498DB"))

3.7 ggplot2可视化

library(ggplot2)

ggplot(df, aes(x = group, y = expression, fill = group)) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  geom_jitter(width = 0.2, size = 2, alpha = 0.6) +
  scale_fill_manual(values = c("Normal" = "#3498DB", "Tumor" = "#E74C3C")) +
  labs(title = "TP53基因表达:肿瘤 vs 正常",
       x = "样本分组", y = "表达量(log2 FPKM)") +
  theme_minimal(base_size = 14) +
  theme(legend.position = "none")

3.8 表格输出

使用 knitr::kable

result_df <- data.frame(
  Gene   = c("TP53", "KRAS", "BRCA1", "MYC"),
  log2FC = c(1.93, -0.82, 2.15, 1.47),
  pvalue = c(0.0012, 0.0435, 0.0003, 0.0089),
  padj   = c(0.0048, 0.1305, 0.0012, 0.0267)
)

knitr::kable(
  result_df,
  caption = "差异表达基因汇总",
  col.names = c("基因", "log2 FC", "P值", "校正P值"),
  digits = 4
)
差异表达基因汇总
基因 log2 FC P值 校正P值
TP53 1.93 0.0012 0.0048
KRAS -0.82 0.0435 0.1305
BRCA1 2.15 0.0003 0.0012
MYC 1.47 0.0089 0.0267

3.9 参数化报告

定义参数(在YAML中)

---
params:
  gene:       "TP53"
  tumor_type: "BRCA"
  threshold:  10
  show_plot:  true
---

在代码块中使用参数

```{r}
# 根据参数动态分析
gene_data <- expr_data[expr_data$gene == params$gene, ]
cat("分析基因:", params$gene, "\n")
cat("样本量:", nrow(gene_data), "\n")

if (params$show_plot) {
  hist(gene_data$expression, main = params$gene)
}
```

第4部分:Quarto:下一代工作流

4.1 什么是Quarto?

Quarto (https://quarto.org/)是下一代开源科学出版系统,统一支持R、Python、Julia等多语言

4.1 什么是Quarto?

与R Markdown的关系

R Markdown  →  Quarto
   R专属    →  多语言统一平台

核心优势

  • 🌐 多语言:R + Python + Julia + Observable
  • 📱 响应式设计:移动端友好
  • 🎨 现代外观:更美观的默认样式
  • 🔗 原生交叉引用:无需bookdown
  • 📚 多格式:网站/书籍/幻灯片/论文

4.2 Quarto vs R Markdown

功能 R Markdown Quarto
代码块选项 {r, echo=FALSE} #\| echo: false
图宽 fig.width=8 #\| fig-width: 8
图标题 fig.cap="..." #\| fig-cap: "..."
交叉引用 需bookdown 原生支持
多语言 主要是R R/Python/Julia
网站 blogdown/pkgdown 原生支持
幻灯片 xaringan/ioslides revealjs原生支持

4.3 Quarto代码块语法

Quarto风格(推荐)

```{r}
#| label: fig-tp53
#| echo: false
#| fig-width: 8
#| fig-height: 5
#| fig-cap: "TP53基因表达分布"

hist(rnorm(100, 10, 2), main = "TP53表达", xlab = "表达量")
```

交叉引用

如 @fig-tp53 所示,TP53在肿瘤组中显著上调。

见 @tbl-results 的差异基因汇总结果。

4.4 Quarto多语言支持

## Python分析

```{python}
import pandas as pd
import numpy as np

df = pd.DataFrame({'expr': np.random.normal(10, 2, 100)})
df.describe()
```

## R可视化

```{r}
library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point(color = "steelblue", size = 3) +
  theme_minimal()
```

第5部分:可重复性研究最佳实践

5.1 可重复性研究原则

为什么重要?

“科学的进步建立在可重复验证的基础上”

环境记录

# 记录会话信息(放在报告末尾)
sessionInfo()

# 使用renv管理依赖(推荐)
renv::init()       # 初始化项目
renv::snapshot()   # 保存包版本
renv::restore()    # 还原环境

项目标准结构

project/
├── data/       # 原始数据(只读)
├── analysis/   # 分析脚本
├── output/     # 结果输出
├── figures/    # 图表
├── report.qmd  # 主报告
└── renv.lock   # 环境锁定文件

5.2 代码书写规范

命名规范

# ✅ 推荐:描述清晰,小写+下划线
calculate_bmi <- function(weight_kg, height_m) { }
tumor_samples <- c("T1", "T2", "T3")
mean_expression <- mean(expr)

# ❌ 避免:含糊简写
calc <- function(w, h) { }
x <- c("T1", "T2", "T3")
m <- mean(expr)

函数文档(roxygen2风格)

#' 计算差异表达基因
#'
#' @param expr_matrix 表达矩阵(基因×样本)
#' @param group 分组向量
#' @param alpha 显著性阈值,默认0.05
#' @return 包含log2FC和p值的数据框
find_de_genes <- function(expr_matrix, group, alpha = 0.05) {
  # 实现...
}

5.3 生信分析报告模板

标准报告结构

## 1. 研究背景
研究目的、数据来源、分析策略

## 2. 数据与方法
- 数据集描述(样本数、基因数)
- 分析流程(质控→标准化→差异分析)
- 软件版本:`sessionInfo()`

## 3. 结果
### 3.1 数据质控
### 3.2 差异表达分析
### 3.3 功能富集分析(GO/KEGG)

## 4. 讨论与结论

## 5. 附录
- 完整代码
- 会话信息(`sessionInfo()`

5.4 输出格式选择

根据场景选择格式

场景 推荐格式 配置
实验室内部汇报 HTML output: html_document
论文附件/投稿 PDF output: pdf_document
与非R用户协作 Word output: word_document
展示汇报 Reveal.js幻灯片 format: revealjs
在线课程/教材 Quarto网站 project: website
# 同时生成多种格式
output:
  html_document: default
  pdf_document:
    toc: true
  word_document: default

课程总结

本讲要点回顾

Markdown

  • 轻量级标记语言,专注内容
  • 标题(#)、粗体(**)、斜体(*
  • 列表、表格、链接、公式

R Markdown

  • 三要素:YAML + Markdown + 代码块
  • 代码块选项控制输出
  • 内联代码实现动态报告
  • 参数化报告批量生成

Quarto

  • 下一代科学出版系统
  • 多语言支持(R/Python/Julia)
  • 原生交叉引用和多种格式

最佳实践

  • renv管理依赖环境
  • 规范的项目目录结构
  • sessionInfo()记录环境
  • 代码命名清晰规范

课程作业

基础任务(必做)

  1. 用R Markdown创建一份TP53基因表达分析报告,包含:
    • 研究背景(Markdown文本)
    • 数据生成(R代码块)
    • 箱线图(ggplot2)
    • 差异分析结果(knitr::kable表格)
    • 内联代码描述结果

进阶任务(选做)

  1. 将R Markdown报告转换为Quarto格式(使用#|选项)
  2. 创建参数化报告,支持切换分析不同基因

速查表资源

延伸阅读

Questions?

王诗翔 副教授
中南大学生物医学信息系

📧 wangshx@csu.edu.cn
🐙 https://github.com/WangLabCSU

下节课预告

  • 🔬 上机实验练习
  • 📊 撰写你的第一份生信分析报告

谢谢!