17  HTML 文档

从本章开始,接下来的三个章节都围绕数据交流的工具及其案例展开。日常工作中,有的需要产出具有丰富交互内容的网页文档(HTML 文档),有的需要产出排版精美、符合格式要求的、可打印的便携式文档(PDF 文档),有的需要可协作共享、可编辑修改的办公文档(Office 文档)。在 R 语言社区,陆续出现两套解决方案,一个是以 rmarkdown 包为核心的 R Markdown 生态,另一个是以 Quarto 为核心的文档写作和发布系统。继 R Markdown 出现 10 余年后,2022 年 RStudio 公司发布 Quarto 系统,整合 R Markdown 生态,提供统一的语法。截止写作时间,相比于成熟的 R Markdown 生态,Quarto 系统还在路上。因此,不拘泥于 R Markdown 还是 Quarto,根据使用场景、实践经验、工具现状,选择最合适的工具介绍,整体上,以 Quarto 为主,R Markdown 补位的方式介绍。

17.1 文档元素

无论是 R Markdown 还是 Quarto,都是站在巨人 Pandoc 的肩膀上,Pandoc 在普通 Markdown 的基础上提供了许多扩展支持,通过一些简单的标记,大大丰富了文档内容,下面介绍的内容适用于 R Markdown 和 Quarto,无论文档最终的输出格式如何。

17.1.1 样式

文字样式,如加粗、倾斜、上下标等。

Markdown 语法 输出
*斜体*, **加粗**, ***粗斜体***
斜体, 加粗, 粗斜体
上角标^2^ / 下角标~2~
上角标2 / 下角标2
~~删除线~~
删除线
`代码`
代码

17.1.2 图片

其一插入现成的图片,其二插入代码生成的图片

(a) versicolor 杂色鸢尾

(b) setosa 山鸢尾

(c) virginica 弗吉尼亚鸢尾

图 17.1: 三种鸢尾花

flowchart LR
  A[Hard edge] --> B(Round edge)
  B --> C{Decision}
  C --> D[Result one]
  C --> E[Result two]
flowchart LR
  A[Hard edge] --> B(Round edge)
  B --> C{Decision}
  C --> D[Result one]
  C --> E[Result two]
图 17.2: 流程图

ggplot2 绘制的图形

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

图 17.3: 一幅简单的 ggplot2 图形

17.1.3 表格

Markdown 原生支持的表格和 knitr 包制作的表格。

表格 17.1: 鸢尾花数据集
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
knitr::kable(head(iris, 3))
表格 17.2: 鸢尾花数据集
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa

17.1.4 列表

常见的列表有无序列表、有序列表及其嵌套。

表格 17.3: 几种列表
Markdown 语法 输出
* 无序列表
    + 子条目 1
    + 子条目 2
        - 子子条目 1
  • 无序列表
    • 子条目 1
    • 子条目 2
      • 子子条目 1
*   条目 2

    继续 (缩进 4 格)
  • 条目 2

    继续 (缩进 4 格)

1. 有序列表
2. 条目 2
    i) 子条目 1
         A.  子子条目 1
  1. 有序列表
  2. 条目 2
    1. 子条目 1
      1. 子子条目 1
(@)  第一个人是好的

第二个人是坏的

(@)  第三个人是丑陋的
  1. 第一个人是好的

第二个人是坏的

  1. 第三个人是丑陋的
::: {}
1. 一个列表
:::

::: {}
1. 又一个列表
:::
  1. 一个列表
  1. 又一个列表
术语
: 定义
术语

定义

(@) 中添加标识符,如 (@good) 就可以引用列表中的条目 (1)。

17.1.5 引用

除了引用外部书籍、文章、刊物等的内容,还有长文档内部的交叉引用,这项功能是非常需要的,涉及图、表、公式、定理,参考文献,列表条目等。

17.1.6 脚注

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

— Paul Murrell

17.1.7 公式

公式分两种情况,其一是行内公式,其二是行间公式。前者一对美元符号夹住数学公式,美元符号与字母之间不能有空格,比如 $\beta$ 渲染出来的效果是 \(\beta\) 。后者是两对美元符号夹住公式,比如 $$\beta$$ 渲染出来的效果如下:

\[\beta\]

行内公式一般用来写数学符号,行间公式一般用来排版数学公式,特别是多行公式。行间公式可以编号,也可以不编号,编号通常是了交叉引用。

\[\mathbf{y} = X\boldsymbol{\beta} + \boldsymbol{\epsilon}\]

排版行间公式有很多不同的 LaTeX 环境,最常见的有两种,一种是多个公式逐行排,一种是长公式折行,常常都要求对齐。举例来说,线性模型的两种表示方式,一种是矩阵向量式,一种是数据结构式,见 方程式 17.1

\[ \begin{aligned} \mathbf{y} &= X\boldsymbol{\beta} + \boldsymbol{\epsilon} \\ y_i &= \mathbf{x}_i\boldsymbol{\beta} + \epsilon_i \end{aligned} \tag{17.1}\]

在行间公式中,使用 split 公式环境排版一个长公式,这个公式是折成多行的,表达一个计算过程。举例来说,线性模型回归系数的最小二乘估计 \(\hat{\boldsymbol{\beta}}\) 的方差的计算过程,见 方程式 17.2

\[ \begin{split} \mathsf{Var}\{\hat{\boldsymbol{\beta}}\} & =\mathsf{Var}\{(X{^\top}X)^{-1}X{^\top}\mathbf{y}\}\\ & =(X{^\top}X)^{-1}X{^\top}\mathsf{Var}\{\mathbf{y}\}\big((X{^\top}X)^{-1}X{^\top}\big){^\top}\\ & =(X{^\top}X)^{-1}X{^\top}\mathsf{Var}\{\mathbf{y}\}X(X{^\top}X)^{-1}\\ & =(X{^\top}X)^{-1}X{^\top}\sigma^{2}IX(X{^\top}X)^{-1}\\ & =(X{^\top}X)^{-1}\sigma^{2} \end{split} \tag{17.2}\]

值得注意,

  1. LaTeX 命令 \mathbf 只对英文字母 \(a,b,c,A,B,C\) 加粗,对希腊字母 \(\theta,\alpha,\beta,\ldots,\gamma\) 加粗应该使用命令 \boldsymbol

  2. Quarto 文档中将行间公式中成对 $$ 转化为 LaTeX 中的 equation 环境。Quarto 不支持在多行公式逐行编号,也不支持在多行公式中对某一(些)行编号。而在 LaTeX 文档中,这些全都支持,可以说公式排版是 LaTeX 最突出的优势。

  3. MathJax 支持公式宏定义,如定义命令 \bm 对希腊字母加粗。在 Quarto 文档中插入如下代码,用命令 \boldsymbol 定义一个新的命令 \bm,这种做法很常见,用来简少公式排版的工作量。

    $$
    \def\bm#1{{\boldsymbol #1}}
    $$

17.2 制作报告

Quarto Report 文档

17.2.1 SQL 查询

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

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

dbListTables(conn)
 [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)

17.3 制作演示

Quarto Presentation

17.4 编写书籍

Quarto Book 网页格式


  1. (on the difference of Lattice (which eventually was called grid) and Trellis) DSC 2001, Wien (March 2001)↩︎