第 13 章 文档元素

knitr 将 R Markdown 文件转化为 Markdown 文件, Pandoc 可以将 Markdown 文件转化为 HTML5、Word、PowerPoint 和 PDF 等文档格式。

rmarkdown 支持的输出格式rmarkdown 支持的输出格式rmarkdown 支持的输出格式rmarkdown 支持的输出格式

图 13.1: rmarkdown 支持的输出格式

rmarkdown 自 2014年09月17日在 CRAN 上发布第一个正式版本以来,逐渐形成了一个强大的生态系统,世界各地的开发者贡献各种各样的扩展功能,见图 13.2

图 13.2: rmarkdown 生态系统

R Markdown 概念图

图 13.3: R Markdown 概念图

13.1 控制选项

Using SQL in RStudio

library(DBI)
conn <- DBI::dbConnect(RSQLite::SQLite(),
  dbname = system.file("db", "datasets.sqlite", package = "RSQLite")
)

Base R 内置的数据集都整合进 RSQLite 的样例数据库里了,

##  [1] "BOD"              "CO2"              "ChickWeight"      "DNase"           
##  [5] "Formaldehyde"     "Indometh"         "InsectSprays"     "LifeCycleSavings"
##  [9] "Loblolly"         "Orange"           "OrchardSprays"    "PlantGrowth"     
## [13] "Puromycin"        "Theoph"           "ToothGrowth"      "USArrests"       
## [17] "USJudgeRatings"   "airquality"       "anscombe"         "attenu"          
## [21] "attitude"         "cars"             "chickwts"         "esoph"           
## [25] "faithful"         "freeny"           "infert"           "iris"            
## [29] "longley"          "morley"           "mtcars"           "npk"             
## [33] "pressure"         "quakes"           "randu"            "rock"            
## [37] "sleep"            "stackloss"        "swiss"            "trees"           
## [41] "warpbreaks"       "women"

随意选择 5 行数据记录,将结果保存到变量 iris_preview

SELECT * FROM iris LIMIT 5;

查看变量 iris_preview 的内容

iris_preview
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa

结束后关闭连接

dbDisconnect(conn = conn)

13.2 Markdown

Markdown 为核心,Pandoc’s Markdown 和 R Markdown 仅介绍扩展的功能,三剑客 Markdown & Pandoc’s Markdown & R Markdown,Markdown for scientific writing

首先介绍 Markdown 在强调、标题、列表、断行、链接、图片、引用、代码块、LaTeX 公式等使用方式,然后在 Markdown 的基础上介绍 Pandoc’s Markdown 功能有加强的地方,R Markdown 在 Pandoc’s Markdown 的基础上介绍功能有加强的地方。

Markdown 基础语法见 RStudio IDE 自带的 Markdown 手册:RStudio 顶部菜单栏 -> Help -> Markdown Quick Reference,这里主要介绍一下Markdown 高级语法,特别是 Pandoc’s Markdown,其实是 Pandoc 提供了很多对 Markdown 的扩展支持,下面介绍一下被 Pandoc 加强后的 Markdown 表格、图片和公式的使用

13.2.1 列表

  • 有序的列表

    1. 第一条
    2. 第二条
  • 无序的列表

    • 第一条

    • 第二条

    • here is my first list item.

    • and my second.

  • 嵌套的列表

    1. 有序
    2. Item 2
    3. Item 3
      • Item 3a
      • Item 3b
    • 无序
    • Item 2
      • Item 2a
      • Item 2b

定义型列表中包含代码

Term 1

Definition 1

Term 2 with inline markup

Definition 2

{ some code, part of Definition 2 }

Third paragraph of definition 2.

定义类型的列表,紧凑形式

Term 1
Definition 1
Term 2
Definition 2a
Definition 2b

无序列表

  • fruits
    • apples
      • macintosh
      • red delicious
    • pears
    • peaches
  • vegetables
    • broccoli
    • chard

对应 LaTeX 列表环境里的有序环境,通篇计数

  1. My first example will be numbered (1).
  2. My second example will be numbered (2).

Explanation of examples.

  1. My third example will be numbered (3).

(@) 环境可以引用

  1. 这是一个好例子

正如 (4) 所指出的那样,

列表里包含代码块

  • item one
  • item two
{ my code block }

显示反引号 `

13.2.2 引用

注意在引用末尾空两格,出处另起一行,引用名人名言:

It’s always better to give than to receive.

Trellis graphics are a bit like hash functions: you can be close to the target, but get a far-off result.51

— Dieter Menne

If you imagine that this pen is Trellis, then Lattice is not this pen.52

— Paul Murrell

You’re overlooking something like line 800 of the documentation for xyplot. […] It’s probably in the R-FAQ as well, since my original feeling was that this behaviour was chosen in order to confuse people and see how many people read the FAQ… :) 53

— Barry Rowlingson

13.2.3 表格

插入表格很简单的,复杂的表格制作可以借助 R 包 knitr 提供的 kable 函数以及 kableExtra 包54,此外谢益辉的书籍 bookdown: Authoring Books and Technical Documents with R Markdown 中也有一节专门介绍表格 https://bookdown.org/yihui/bookdown/tables.html

kable 支持多个表格并排,

knitr::kable(
  list(
    head(iris[, 1:2], 3),
    head(mtcars[, 1:3], 5)
  ),
  caption = 'A Tale of Two Tables.', booktabs = TRUE
)
表 13.1: A Tale of Two Tables.
Sepal.Length Sepal.Width
5.1 3.5
4.9 3.0
4.7 3.2
mpg cyl disp
Mazda RX4 21.0 6 160
Mazda RX4 Wag 21.0 6 160
Datsun 710 22.8 4 108
Hornet 4 Drive 21.4 6 258
Hornet Sportabout 18.7 8 360

在表格中引入数学符号

kableExtra 、broom 和 pixiedust 包实现表格样式的精细调整,如黄湘云制作的 样例

13.2.4 图片

利用 knitr::include_graphics 函数在代码块中插入图片是很简单的,如图13.4所示,图、表的标题很长或者需要插入脚注,可以使用[文本引用][text-references]

(ref:footnote)

图 13.4: (ref:footnote)

par(mar = c(4.1, 4.1, 0.5, 0.5))
plot(rnorm(10), xlab = "", ylab = "")
(ref:fig-cap)

图 12.26: (ref:fig-cap)

控制图片插入的宽度参考谢益辉的博客: CSS 的位置属性以及如何居中对齐超宽元素 https://yihui.name/cn/2018/05/css-position/

  • One

  • Two

    还可以在列表环境中插入图片

  • Three

根据代码动态生成图片,并插入文档中;外部图片插入文档中

plot(AirPassengers)
时间序列图

图 13.5: 时间序列图

plot(pressure)
plot(AirPassengers)
2行1列布局2行1列布局

图 13.6: 2行1列布局

plot(pressure)
plot(AirPassengers)
1行2列布局1行2列布局

图 13.7: 1行2列布局

plot(pressure)
plot(AirPassengers)
plot(pressure)
plot(AirPassengers)
2x2图布局2x2图布局2x2图布局2x2图布局

图 13.8: 2x2图布局

(ref:fig-cap) 测试文本引用 (ref:text-references) 图表标题很长可使用[文本引用][text-references] (ref:footnote) 表格标题里插入脚注,但是 ebooks 不支持这样插入脚注[^longnote] [^longnote]: Here’s one with multiple blocks. [text-references]: https://bookdown.org/yihui/bookdown/markdown-extensions-by-bookdown.html#text-references

13.2.5 公式

行内公式一对美元符号 \(\alpha\) 或者 \(\alpha+\beta\),行间公式 \[\alpha\] 或者 \[\alpha + \beta\] 对公式编号,如公式 (13.1)

\[\begin{equation} L(\beta,\boldsymbol{\theta}) = f(y;\beta,\boldsymbol{\theta}) = \int_{\mathbb{R}^{n}}N(t;D\beta,\Sigma(\boldsymbol{\theta}))f(y|t)dt \tag{13.1} \end{equation}\]

多行公式分别编号,如公式(13.2) 和公式(13.3)

\[\begin{align} \log\{\frac{p_i}{1-p_i}\} & = T_{i} = d(x_i)'\beta + S(x_i) + Z_i \tag{13.2}\\ \log(\lambda_i) & = T_{i} = d(x_i)'\beta + S(x_i) + Z_i \tag{13.3} \end{align}\]

多行公式中对某一(些)行编号,如公式 (13.4) 和 公式 (13.5)

\[\begin{align} g(X_{n}) &= g(\theta)+g'({\tilde{\theta}})(X_{n}-\theta) \\ \sqrt{n}[g(X_{n})-g(\theta)] &= g'\left({\tilde{\theta}}\right) \sqrt{n}[X_{n}-\theta ] \tag{13.4} \\ \log(\lambda_i) & = T_{i} = d(x_i)'\beta + S(x_i) + Z_i \tag{13.5} \end{align}\]

多行公式共用一个编号,如公式 (13.6)

\[\begin{equation} \begin{aligned} L(\beta,\boldsymbol{\theta}) & = \int_{\mathbb{R}^{n}} \frac{N(t;D\beta,\Sigma(\boldsymbol{\theta}))f(y|t)}{N(t;D\beta_{0},\Sigma(\boldsymbol{\theta}_{0}))f(y|t)}f(y,t)dt\\ & \varpropto \int_{\mathbb{R}^{n}} \frac{N(t;D\beta,\Sigma(\boldsymbol{\theta}))}{N(t;D\beta_{0},\Sigma(\boldsymbol{\theta}_{0}))}f(t|y)dt \\ &= E_{T|y}\left[\frac{N(t;D\beta,\Sigma(\boldsymbol{\theta}))}{N(t;D\beta_{0},\Sigma(\boldsymbol{\theta}_{0}))}\right] \end{aligned} \tag{13.6} \end{equation}\]

推荐在 equation 公式中,使用 split 环境,意思是一个公式很长,需要拆成多行,如公式(13.7)

\[\begin{equation} \begin{split} \mathrm{Var}(\hat{\beta}) & =\mathrm{Var}((X'X)^{-1}X'y)\\ & =(X'X)^{-1}X'\mathrm{Var}(y)((X'X)^{-1}X')'\\ & =(X'X)^{-1}X'\mathrm{Var}(y)X(X'X)^{-1}\\ & =(X'X)^{-1}X'\sigma^{2}IX(X'X)^{-1}\\ & =(X'X)^{-1}\sigma^{2} \end{split} \tag{13.7} \end{equation}\]

注意,\mathbf 只对字母 \(a,b,c,A,B,C\) 加粗,mathjax 不支持公式中使用 \bm\(\theta,\alpha,\beta,\ldots,\gamma\) 加粗,应该使用 \boldsymbol

13.3 表格

knitrkable() 函数提供了制作表格的基本功能 https://bookdown.org/yihui/rmarkdown-cookbook/tables.htmlflextable 支持更加细粒度的表格定制功能。beautifyR 整理 Markdown 表格非常方便,datapasta 快速复制粘贴 data.frame 和 tibble 类型的数据表格。rpivotTable 不更新了,pivottabler 在更新,内容似乎更好。remedy 提供了更加通用的 Markdown 写作功能,简化创作的技术难度。

13.4 流程图

nomnoml 流程图、思维导图

nomnoml::nomnoml(" 
#stroke: #26A63A
#.box: fill=#8f8 dashed visual=note
#direction: down

[Sweave-test-1.Rnw] -> utils::Sweave() [Sweave-test-1.tex|Sweave-test-1-006.pdf|Sweave-test-1-007.pdf]
[Sweave-test-1.Rnw] -> utils::Stangle() [Sweave-test-1.R]
[Sweave-test-1.tex] -> tools::texi2pdf() [Sweave-test-1.pdf]
[Sweave-test-1.tex] -> tools::texi2dvi() [Sweave-test-1.dvi]
")

13.5 编程语言引擎

语法高亮

## Warning in matrix(names(knitr::knit_engines$get()), ncol = 3, byrow = TRUE):
## data length [58] is not a sub-multiple or multiple of the number of rows [20]
表 13.2: knitr 支持的引擎
awk bash coffee
gawk groovy haskell
lein mysql node
octave perl psql
Rscript ruby sas
scala sed sh
stata zsh highlight
Rcpp tikz dot
c cc fortran
fortran95 asy cat
asis stan block
block2 js css
sql go python
julia sass scss
R bslib targets
theorem lemma corollary
proposition conjecture definition
example exercise hypothesis
proof remark solution
nomnoml awk bash

Pandoc 通过 LaTeX 环境 lstlisting 支持语法高亮,比如

表 13.3: Pandoc 支持的语法高亮
ABAP IDL Plasm ACSL inform POV Ada
Java Prolog Algol JVMIS Promela Ant ksh
Python Assembler Lisp R Awk Logo Reduce
bash make Rexx Basic Mathematica RSL C
Matlab Ruby C++ Mercury S Caml MetaPost
SAS Clean Miranda Scilab Cobol Mizar sh
Comal ML SHELXL csh Modula-2 Simula Delphi
MuPAD SQL Eiffel NASTRAN tcl Elan Oberon-2
TeX erlang OCL VBScript Euphoria Octave Verilog
Fortran Oz VHDL GCL Pascal VRML Gnuplot
Perl XML Haskell PHP XSLT HTML PL/I

13.6 快速创建书籍项目

在指定目录创建 Book 项目

bookdown:::bookdown_skeleton("~/bookdown-demo")

项目根目录的文件列表

directory/
├──  index.Rmd
├── 01-intro.Rmd
├── 02-literature.Rmd
├── 03-method.Rmd
├── 04-application.Rmd
├── 05-summary.Rmd
├── 06-references.Rmd
├── _bookdown.yml
├── _output.yml
├──  book.bib
├──  preamble.tex
├──  README.md
└──  style.css

13.7 Markdown 生态系统

大量基于 Markdown 的软件工具,比如 Wiki Gollum、 Typora 和 VS Code 等

Pandoc’s Markdown 在 Markdown 的基础上添加的功能

13.8 R Markdown 生态系统

R Markdown 站在巨人的肩膀上,这些巨人有 MarkdownPandocLaTeX 等。

markdown 简洁设计哲学, Sweave 文学编程思想,期间各种工具粉墨登场,最后分别回到 Pandoc 和 R Markdown

表 13.4: R Markdown 生态系统
Package Title
addinsOutline RStudio Addins for Show Outline of a R Markdown/LaTeX Project
blogdown Create Blogs and Websites with R Markdown
bookdown Authoring Books and Technical Documents with R Markdown
bsplus Adds Functionality to the R Markdown + Shiny Bootstrap Framework
chronicle Grammar for Creating R Markdown Reports
distill R Markdown Format for Scientific and Technical Writing
flexdashboard R Markdown Format for Flexible Dashboards
govdown GOV.UK Style Templates for R Markdown
jds.rmd R Markdown Templates for Journal of Data Science
komaletter Simply Beautiful PDF Letters from Markdown
liftr Containerize R Markdown Documents for Continuous Reproducibility
mailmerge Mail Merge Using R Markdown Documents and ‘gmailr’
memoiR R Markdown and Bookdown Templates to Publish Documents
memor A rmarkdown Template that Can be Highly Customized
officedown Enhanced R Markdown Format for ‘Word’ and ‘PowerPoint’
pagedown Paginate the HTML Output of R Markdown with CSS for Print
parsermd Formal Parser and Related Tools for R Markdown Documents
posterdown Generate PDF Conference Posters Using R Markdown
prereg R Markdown Templates to Preregister Scientific Studies
prettydoc Creating Pretty Documents from R Markdown
quarto R Interface to ‘Quarto’ Markdown Publishing System
radix R Markdown Format for Scientific and Technical Writing
reportfactory Lightweight Infrastructure for Handling Multiple R Markdown Documents
revealjs R Markdown Format for reveal.js Presentations
rmdfiltr Lua-Filters for R Markdown
rmdformats HTML Output Formats and Templates for rmarkdown Documents
rmdplugr Plugins for R Markdown Formats
rmdshower R Markdown Format for shower Presentations
rticles Article Formats for R Markdown
siteymlgen Automatically Generate _site.yml File for R Markdown
stevetemplates Steve’s R Markdown Templates
trackdown Collaborative Writing and Editing of R Markdown (or Sweave) Documents in Google Drive
tufte Tufte’s Styles for R Markdown Documents
tufterhandout Tufte-style html document format for rmarkdown
uiucthemes R Markdown Themes for UIUC Documents and Presentations
vitae Curriculum Vitae for R Markdown
webexercises Create Interactive Web Exercises in R Markdown (Formerly ‘webex’)
ymlthis Write YAML for R Markdown, bookdown, blogdown, and More

13.9 支持网页图形

library(ggplot2)
p1 <- ggplot(data = iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point() +
  theme_minimal()

p2 <- ggplot(data = iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) +
  geom_point() +
  theme_minimal()

library(patchwork)
p1 + p2
组合 ggplot2 图形

图 13.9: 组合 ggplot2 图形

ggiraph 将 ggplot 对象转化为网页

library(ggiraph)
girafe(code = print(p1 + p2), width_svg = 8, height_svg = 3)

13.10 支持 Shiny App

将动态图形嵌入 Shiny App 中

图 13.10: A Shiny app created via the ggiraph package; you can see a live version at https://xiangyun.shinyapps.io/01-iris-ggiraph/.