第 4 章 基于 R Markdown 工作与学习
4.1 发邮件:blastula
使用者有的时候可能需要批量发送定制版邮件,有些软件提供了相应选项,利用 R Markdown 也可以实现这一功能。具体而言,借助 blastula
包 (R-blastula?),可以将 R Markdown 文档呈现在电子邮件正文并发送电子邮件。要将 R Markdown 文档呈现到电子邮件中,需要在文档中使用输出格式 blastula::blastula_email
,例如:
---
title: 周报
output: blastula::blastula_email
---
尊敬的客户,
以下是对 `iris` 数据的分析:
```{r}
summary(iris)
plot(iris[, -5])
```
若感兴趣请及时回复。
祝好, 张三
这个将 R Markdown 文档会通过函数 blastula::render_email()
来呈现,输出将被传递给 blastula::smtp_send()
,它将发送电子邮件。需要注意的是,smtp_send()
需要一个电子邮件服务器和使用者的凭证(credentials)。
如果使用 RStudio Connect,还可以 在https://solutions.rstudio.com/examples/blastula-overview/ 上找到更多的例子,包括自动的、有条件的和参数化的电子邮件。
4.2 制作 R 包:fusen
R 语言的日常使用离不开 R 包,而对于很多使用者来说,亲手制作 R 包无疑是一项有趣的工作,它不仅可以封装一些自己常用的函数,大大加速日常的工作,还可以将自己的创意通过 GitHub 或者 CRAN 发布,让更多的人了解并使用,从而给自己带来极大的成就感,甚至于获得实质性的成就25。
相信有着很多制作 R 包经验的使用者都被其繁琐的制作流程所困扰。通常情况下,制作一个 R 包需要完成如下几个内容:
- R 函数
- 函数注释
- 函数示例
- DESCRIPTION 文件
- NAMESPACE 文件
- vignette 文档(可选)
很多高级开发人员厌倦了在 R 文件、测试文件、vignette 文件之间频繁切换,特别是在更改函数参数的时候,开发者需要更改示例,并在多个地方进行单元测试,很容易漏了某一个地方。而使用 fusen
(R-fusen?) 制作 R 包则减少了这些困扰,使用者只需要在同一个文件中完成 R 包,与一个函数相关的所有内容都在一个地方,减少了遗漏的风险。
而对于更多未曾接触过 R 包制作的人来说,制作 R 包这个任务初听起来似乎较为复杂,会“劝退”很多人。fusen
则为那些以前从未写过 R 包但知道如何使用 R Markdown 的使用者提供了亲手创建 R 包的机会,这个包可以帮助他们迈出第一步。
使用 fusen
制作 R 包需要以下几个步骤:
通过 RStudio 选项
File > New Project > New directory > Package using {fusen}
来创建项目;选择模板:首次使用可以选择模板
teaching
,或者直接使用函数create_fusen("path/to/new/project", template = "teaching")
;希望更多自定义功能的用户可以选择模板full
。编写并运行模板内的对应内容。
下面以 teaching
模板为例进行详细介绍,而 full
模板在 teaching
模板的基础上添加了诸如发布到 GitHub、包含数据文件等功能,原理上是相同的,模板内部也有详细的解释可供阅读。
在选择模板 teaching
后,会自动生成 Rmd 文件 flat_teaching.Rmd
,其中第一个代码框为:
调用 testthat
包 (Hadley Wickham 2022) 可以帮助使用者更好地测试代码。
下一个代码框可以帮助使用者对创建的包进行描述并进行授权,其中包含了标题(Title
)、描述(Description
)以及作者信息(Authors
)等内容,一个简化的内容如下:
fill_description(fields = list(Title = "My Awesome Package"))
::use_mit_license("Sébastien Rochette") usethis
接下来需要按照模板的引导来编写函数,例如模板提供了示例函数:
```{r function-add_one}
#' Add one to any value
#'
#' @param value A numeric value
#'
#' @return Numeric. value + 1
#' @export
add_one <- function(value) {
result <- value + 1
return(result)
} ```
add_one()
函数的注释使用了 roxygen 语法,以 #'
开头的每一行代表了这个函数的一个特征,其中包括:
@param
:函数涉及的参数,书写的格式为@param 参数 参数解释
,每个参数对应一个@param
;@return
:函数输出内容的解释;@export
:输出以上内容所必须的命令。
除此之外,常用的其它参数包括:
@title
:函数的详细名称;@description
:函数功能的解释;@details
:使用函数的细节;@examples
:函数的示例,但是使用fusen
制作 R 包时可以直接在对应函数下方添加以examples
为名称的代码框:
```{r examples-add_one}
add_one(12)
add_one(56) ```
这样就会自动在其上方的函数描述中加入对应的示例。在示例后面还需要加入测试函数来确保函数可以正常运行,这里的 test_that()
函数就来自于一开始调用的 testthat
包:
```{r tests-add_one}
test_that("add_one works", {
expect_equal(add_one(12), 13)
expect_equal(add_one(56), 57)
}) ```
需要注意的是,如果想一个包中包含多个函数,则需要对每个函数都添加 function
、examples
和 tests
代码框,并将其放入不同的章节中(即在模板中新添加一个以 #
为开头的章节,如 # Add two to any value
)。另外,由于相应功能的代码框会在名称部分加以区分,所以对于不同函数,需要在代码框名称后面添加标记,例如本节例子中的 function-add_one
、examples-add_one
和 tests-add_one
。
最后,需要运行以下代码来将 Rmd 文件转化成一个完整的包。
::inflate(
fusenflat_file = "dev/flat_teaching.Rmd",
vignette_name = "Get started",
check = TRUE
)
更多关于 fusen
包的细节请参见 https://github.com/ThinkR-open/fusen/。
4.3 制作简历:datadrivencv
无论是在找工作、申请高校,还是在制作个人网站时,简历都是必不可少的,一个形式简洁、内容丰富的简历可以让读者在短时间内了解一个人。但是在制作简历时,往往会在寻找模板、调整格式上下很多功夫,尤其是在更新简历时,往往需要进行大量的调整,甚至于从头再来。
就像 R Markdown 制作的初衷是帮助使用者将注意力集中于内容上一样,datadrivencv
包 (R-datadrivencv?) 的目标也是将内容与输出分离,利用 R Markdown 的特性,可以使用相同的代码同时生成简历的交互式 HTML 以及 PDF 版本,这将大大减轻制作以及维护简历的工作量。
由于 datadrivencv
包目前没有发布到 CRAN 上,只能通过 GitHub 来下载:
# install.packages("devtools")
# 可能需要安装的依赖包:remotes::install_github('mitchelloharawild/icons@v0.1.0')
::install_github("nstrayer/datadrivencv") devtools
使用 datadrivencv
包的第一步是使用 use_data_driven_cv()
函数:
::use_datadriven_cv(
datadrivencvfull_name = "Nick Strayer",
data_location = "https://docs.google.com/spreadsheets/d/14MQICF2F8-vf8CKPF1m4lyGKO6_thG-4aSwat1e2TWc",
pdf_location = "https://github.com/nstrayer/cv/raw/master/strayer_cv.pdf",
html_location = "nickstrayer.me/cv/",
source_location = "https://github.com/nstrayer/cv"
)
其中的参数有:
full_name
:使用者的姓名;data_location
:保存所有数据的电子表格的路径。可以是指向包含四种数据类型的多个工作表的谷歌工作表的 URL,也可以是指向包含四个包含必要数据的.csv
文件夹的路径,例如data_location = "data/cv_data/"
。这四个文件夹命名需要分别为entries.csv
、language_skills.csv
、text_blocks.csv
以及contact_info.csv
,分别包含作者的工作经历、编程语言能力、简历不同模块的简介以及联系方式。这四个文件的模板可以从 https://github.com/cosname/rmarkdown-guide/tree/master/data/cv_data 中下载;pdf_location
:发布简历 PDF 版本的网址;html_location
:发布简历 HTML 版本的网址;source_location
:构建简历的代码的位置,填写作者提供的https://github.com/nstrayer/cv
即可。
函数的更多细节可以通过运行 ?datadrivencv::use_datadriven_cv
来查看。当运行这个函数时,会在当前工作目录中添加一系列文件:
cv.rmd
:一个 R Markdown 文件,其中包含了制作简历的各个部分。可以通过编辑这个文件来满足具体的个人需求;dd_cv.css
:建立在默认Pagedown
“resume” 模板上的一组自定义 CSS 样式,可以根据需要进行编辑;render_cv.r
:同时构建 PDF 和 HTML 两种格式的简历的脚本;cv_printing_functions.r
:执行将电子表格数据转换为 markdown 或 HTML 并使输出用于 PDF 打印的一系列函数。
在得到上述四个文件,并且按照模板填写完毕相应的 .csv
文件夹后,用 RStudio 打开 cv.rmd
并点击 Knit
即可得到 HTML 格式的简历。如果想进一步生成 PDF 格式的简历,运行 render_cv.r
中的相应函数即可:
# 编译 HTML 版本的简历
::render("cv.rmd",
rmarkdownparams = list(pdf_mode = FALSE),
output_file = "cv.html")
# 编译 PDF 版本的简历到 HTML 版本中,从而可以在 HTML 版本中下载
<- fs::file_temp(ext = ".html")
tmp_html_cv_loc ::render("cv.rmd",
rmarkdownparams = list(pdf_mode = TRUE),
output_file = tmp_html_cv_loc)
# 用 Pagedown 将 HTML 转换至 PDF,生成 PDF 文件
::chrome_print(input = tmp_html_cv_loc,
pagedownoutput = "cv.pdf")
现在这个包还存在着诸多问题,例如提供的简历模板较少、对中文的支持较差等问题,有待进一步优化,但也给了使用者更自由的空间。更多细节请参考 https://github.com/nstrayer/datadrivencv。
4.4 写书和记学习笔记:bookdown
用 R Markdown 还可以实现记笔记甚至写书的功能,本书的写作过程就是通过 R Markdown 进行,其中关键在于 bookdown 包 (Xie 2022a)。这个包被设计为创建由多个 R Markdown 文档组成的长篇文档。例如,如果想写一本书,可以在自己的 R Markdown 文件中编写每个章节,并使用 bookdown 将这些 R Markdown 文件编译成一本书。
对于 RStudio 的用户来说,最简单的开始方法是通过 File -> New Project -> New Directory -> Book Project using bookdown
,用 IDE 创建一个 bookdown 项目,正如图 4.1 所示。
如果不使用 RStudio 或者喜欢在控制台工作,也可以通过调用函数 bookdown:::bookdown_skeleton('your-book-dir')
产生相同的结果。
为了演示用法,下面提供了一个最小的示例,包含同一个目录中的三个文件:
directory
|- index.Rmd
|- 01-intro.Rmd |- 02-analysis.Rmd
下面将显示每个文件的内容并解释它们的作用:
index.Rmd:
--- title: "一个最小的 bookdown 项目" site: bookdown::bookdown_site output: bookdown::gitbook --- # 前言 {-} 内容
第一个文件通常被称为 index.Rmd
。它应该是提供 YAML 前端内容的唯一 R Markdown 文件,它还应该包含一个特殊的 YAML 字段 site: bookdown::bookdown_site
,以便 rmarkdown 知道使用 bookdown 来构建所有 R Markdown 文件,而不是呈现单个 R Markdown 文件。可以使用任何 bookdown输出格式,例如 bookdown::gitbook
、 bookdown::pdf_book
、 bookdown::word_document2
以及 bookdown::epub_book
。
接下来的两个 R Markdown 文件是两个章节:
01-intro.Rmd:
# 第 1 章 这是第 1 章。
02-analysis.Rmd:
# 第 2 章 这是第 2 章。
要呈现这些 R Markdown 文件,应该调用 bookdown::render_book('index.Rmd')
而不是 rmarkdown::render()
。在底端,bookdown 在默认情况下会将所有 R Markdown 文件合并为单个 R Markdown 并编译它。文件按字母顺序合并。这就是为什么在上面的例子中为文件名添加数字前缀的原因。
事实上,可以通过很多设置来自定义一个 bookdown 项目。关于 bookdown 的更全面的概述,可以查看 R Markdown Definitive Guide 的第十八章 “Creating New Formats” (Xie, Allaire, and Grolemund 2018a)。完整文档请参见书籍 bookdown (Xie 2016)。
需要注意的是,本节提供例子内容为英文,若需要编译含中文的文档,则需要加入特殊的命令,如 documentclass: ctexbook
,一个简单的中文书例子请参见: https://github.com/yihui/bookdown-chinese。
4.5 制作网站:blogdown
4.5.1 blogdown 简介
在当今的互联网时代世界,无论从事什么职业,个人网站几乎成为了一张人手必备的的“电子名片”。谢益辉开发的 blogdown 包提供了一种功能全面,且设置简单快速的个人网站架设途径。
基于 R Markdown 的 blogdown 包为个人用户提供一种轻便快速的建立个人静态网站的方案。不同于市面上多数的网站建立方案,静态网站有着众多好处,如文件体型小,铺设速度快,所以更换服务器时更加省时省力。与此同时,blogdown 依赖 R Markdown 文件为基础来生成网站。而 R Markdown 文件本身支持众多强大功能,包括文本的书写,编辑与排版(包括对 \(LaTeX\) 的支持),数据分析,交互性插件(如交互性图表)等。
本书的这个小节将通过一个对新手十分友好的案例来手把手的展示如何快速建立一个可满足日常基本需求的网站,以便用户可快速上手 R 的 blogdown 包。
4.5.2 具体操作
4.5.2.1 安装 blogdown
在开始之前,用户需要确认个人主机已经安装最新版本的 R 和 RStudio。
首先,通过以下一行命令从 CRAN 安装 blogdown 包:
# 安装 blogdown
install.packages("blogdown")
4.5.2.2 创建项目
一个网站可被视为一个 R 项目。想要创建一个新的网站项目,只需要按照下图提示,在 RStudio 菜单栏依次选择文件,新项目,新目录 (File -> New Project -> New Directory
)。完成后,选择用 blogdown 建设网站 (Website using blogdown
),即可看到一个网站项目的具体设置界面。
设置好目录名,只需点击创建项目(Create Project
),RStudio 即会通过 blogdown 包来自动生成一个网站项目。
4.5.2.3 网站铺设
用户可以便捷的通过 RStudio 的基础功能在本地浏览自己的网页项目。用户既可以直接在控制台 (Console) 键入 blogdown::serve_site()
,或在 RStudio 上方的插件 (Addins
) 选项选择铺设网站 (Serve Site
)。
然后 RStudio 应会显示与下图相似的页面。
显示本地铺设成功后,用户既可以通过图形交互页面,点击在本地浏览器打开(在 RStudio 右上角的 Show in new window
)来通过本地浏览器在本地浏览刚刚编辑好的网页。只要网页项目在本地浏览器中被打开后,之后任何在源文件上的改动都会自动在浏览器中进行实时加载,所以并不需要在每次改动后重复点击铺设 (knit
) 网站。
4.5.2.4 内容编辑
位于 RStudio 的右下角,用户可以通过进入内容 content
文件夹来查看并编辑当下网站项目的所有内容页。作为一个初始例子,这里首先打开 2020 年 12 月 01 日的一个文件 content/post/2020-12-01-r-rmarkdown/index.Rmd
。 可以注意到,打开的 Rmarkdown/Rmd
文件的最上方是含有标题 title
,作者 author
等字眼的代码部分,而这个部分被称为 YAML 代码区 (用于设定网页形态)。 当编辑具体网页内容时,用户只需要在 YAML 代码区下方的空白部分进行编写即可。
接下来,这里展示如何在网页中添加代码。如下图所示,只需添加一个 R 代码块,然后输入以下内容,代码就会自动展示在网页上。
library(ggplot2)
summary(Orange)
## Tree age circumference
## 3:7 Min. : 118.0 Min. : 30.0
## 1:7 1st Qu.: 484.0 1st Qu.: 65.5
## 5:7 Median :1004.0 Median :115.0
## 2:7 Mean : 922.1 Mean :115.9
## 4:7 3rd Qu.:1372.0 3rd Qu.:161.5
## Max. :1582.0 Max. :214.0
ggplot(Orange, aes(x = age,
y = circumference,
color = Tree)) +
geom_point() +
geom_line() +
guides(color = "none") +
theme_bw()
此时,如果编辑中的网站项目已经在本地浏览器中打开,用户只需要点击左上角的保存,几秒后即可在浏览器内看到如下图的内容。如果此时用户并没有在本地浏览网页,点击编译 knit
,网站便会在本地的 RStudio 自动生成。
4.5.2.5 网站配置
除了通过编辑 Rmd
文件来实现网站内容的编辑外,用户还可以通过修改 config.yaml
文件内的设定来自定义自己的网站。
例如,打开 config.yaml
文件后,用户可能会看到如下内容:
: /
baseurl: A Hugo website
title: hugo-lithium
theme:
ignoreFiles- \.Rmd$
- \.Rmarkdown$
- _cache$
- \.knit\.md$
- \.utf8\.md$
:
permalinks: /:year/:month/:day/:slug/
post:
menu:
main- name: About
: /about/
url- name: GitHub
: https://github.com/rstudio/blogdown
url- name: Twitter
: https://twitter.com/rstudio url
只需在相应的部分进行编辑,用户就可以根据个人的需求自定义自己的网站,如:
title: 我的网站
:将网站标题修改为“我的网站”name: Weibo
url: 你的微博url
:在菜单中添加个人 Weibo 信息页面的链接
4.5.2.6 小结
目前为止,此节已经展示了如何创建并编辑一个个人化 blogdown 网站的三条基本知识:
- 通过 RStudio 的铺设
Serve Site
功能 或在控制台内键入blogdown::serve_site()
来在本地浏览自己的网站。 - 通过编辑
config.yaml
文件来自定义自己的网站(标题,菜单栏,主题等)。 - 通过编辑处于目录夹中
content
文件夹内的Rmd
文件来编辑具体的网页信息。通过进阶的学习,用户还可以通过修改自定义Rmd
文件的位置来改变他们在网站上显示的结构。
4.5.2.7 部署
那么下一步是什么?选择自然有很多,但最重要的莫过于通过部署编辑完成的网站,以便让他人可以通过互联网直接浏览网站上的内容。
就像之前简短提到过的,因为静态网站本质上就是一个文件夹,所以静态网站与大多数动态网站相比较的一个重要优点就是部署更加简单且快速。那么如何选择用于部署的服务器呢?权衡过上手友好度以及性价比后,Netlify (https://www.netlify.com/) 是一个很不错的选择。
4.5.2.8 Netlify
Netlify 提供的免费服务功能多元,足够满足大多数用户的需求,且部署也十分简单。就算用户之前没有部署网站的经验,也只需创建一个 GitHub 账户,并使用此账户注册并登陆属于用户个人的 Netlify 账户。登陆成功后,只需将网站项目目录中由 blogdown 生成的名为公共 Public/
的文件夹拖入 Netlify 部署页面即可。
一般只需几秒钟,网站就会被成功部署在 Netlify 的服务器上,并可以通过一个格式为 random-word-12345.netlify.com
的域名访问。此域名是 Netlify 自动生成的一个子域名,并支持通过设置修改至自己偏好的字眼。Netlify 提供的一体化部署服务省去了用户在其他服务器上实现自定义设置时往往需要面对的许多麻烦。
不过需要注意的是,每次在本地的 RStudio 编辑完个人网站后,用户需要在控制台输入以下代码来更新你的公共文件夹 Public/
。只有在更新完成后,才可以通过在 Netlify 上次最新版本的 Public/
文件夹来部署你改动过后的网站。
::build_site() blogdown
4.6 制作科技论文的支撑材料
数据驱动是当前科学研究的重要发展趋势。中国科学院生化所吴家睿教授认为,数据驱动的研究范式不仅能够避免研究者可能的主观偏见,而且可以帮助其发现在假设或者现有理论范围之外的全新知识。这种方式不需要假设,主要目的是去获取研究对象的相关信息,克服了假设驱动的研究范式对决定论和因果关系的偏执,进而形成了开放式研究的认识论新体系。
在这样的背景下,越来越多的期刊都鼓励或者要求作者开放研究中使用的原始数据和分析过程,给了 R Markdown 一个新的用武之处。
4.6.1 建议文件结构
论文的支撑材料通常存放在 GitHub 这一类的开源网站上,其文件结构通常是:
|--+ data:子文件夹,用于存放分析使用的数据;
|--+ figures:子文件夹,用于存放生成的图片;
|--+ functions:子文件夹,用于存放一些需要重复调用的函数;
|- supplementary.Rproj:R 项目文件;
|- README.md:使用 Markdown 语法的 README 文件,用于说明项目相关信息;
|- analysis.Rmd:使用 R Markdown 语法的分析文件(可以有多个)。
analysis.Rmd
是支撑材料中的核心文件。它是一个常规的 R Markdown 文档。举例来说,下面的头文件中分别指定了 3 种不同的输出样式。
---
title: Your Title
author: "your@email.com"
date: "2022-5-15"
output:
html_document:
toc: yes
toc_depth: 3
toc_float:
collapsed: no
smooth_scroll: no
md_document:
variant: markdown_github
pdf_document:
toc: yes
toc_depth: '3'
---
为了让生成的图片能够妥善的存放到 figures
文件夹,需要在头文件后面添加一些设置。
```r
knitr::opts_chunk$set(
fig.width = 8,
fig.asp=0.618,
dpi = 300,
warning = FALSE,
fig.path = "figures/Figure-"
)
```
这里将图片的默认宽度和比例分别设置为 8 英寸和 0.618(黄金分割比例),并设置图片分辨率为 300 dpi;与此同时,不显示 R 运行过程中的警告信息;此外,还将图片输出的路径指定到 figures
文件夹中。
4.6.2 分析报告的正文
报告的正文仁者见仁智者见智,不过通常会包含以下几个部分(因为研究论文更多的发表在英文期刊上,所以这里的报告示例使用了英文标题)。
## Required Packages
## Data Processing
## Main Results
## Supporting Results
这基本上是按照数据分析的逻辑组织的,所以就不再赘述了。
如果文档中不涉及动态网页内容,推荐把 R Markdown 文档输出为 Markdown ,因为这样读者可以直接在 GitHub 网站查看相应的结果。
具体做法:
- 在头文件中加入
output: github_document
; - 使用下面的命令将 Rmd 文件编译为 Markdown 文件。注意这里指定了 GitHub Flavored Markdown(gfm)作为输出格式。
library(rmarkdown)
render("analysis.Rmd",md_document(variant = "gfm"))
参考文献
2019 年 7 月 31 日,在国际统计学年会(JSM)上,统计学会会长委员会(COPSS)将当年的考普斯会长奖(COPSS Presidents’ Award)颁发给了 RStudio 公司的首席科学家、R 语言软件包开发者 Hadley Wickham,以表彰他在统计应用领域做出的卓越贡献。考普斯会长奖是统计学领域的最高奖项,由美国统计协会(ASA)、加拿大统计学会(SSC)、国际数理统计学会(IMS)、国际生物统计学会北美东部地区(ENAR)、国际生物统计学会北美西部地区(WNAR)发起,被誉为“统计学界的诺贝尔奖”,每年颁发一次,授予一位在统计学领域作出杰出贡献的青年学者。考普斯会长奖此前几乎都颁发给统计学界的基础研究、应用研究学者,而 Hadley Wickham 是第一位 作为软件开发者的获奖者。Hadley 在 R 语言圈是个如雷贯耳的名字,他创建并发布了很多流行的 R 包,包括著名图形可视化软件包
ggplot2
,以及其他著名的软件包dplyr
、tidyverse
等。↩︎