对于自动化报告的开场白,我希望引用谢老大(原名:谢益辉,p.s.混迹COS论坛的人应该很经常见到此人,没听说过此人的童鞋也应该没怎么用过RStudio,是R的一位高级忍者)对于knitr的一些介绍。
人类和计算机有各自擅长的东西,人擅长下指令,计算机擅长执行指令,而且对计算机来说,一个任务做一遍或是做一百遍可能只有时间上的区别,但一个人要是同一个任务重复做一百遍可能就抓狂了,而且容易出错。另一方面,人还有最大的一个特征就是懒惰;懒没什么错,看怎么个懒法。有人纯粹是混日子的懒,有人是为了更高效率工作而走捷径。用R做自动化报告就是为了提高效率和保证结果可重复。
我想knitr最重要的两点是:
提高报告撰写效率:通过knitr我们可以直接撰写研究报告,避免每次需要把实验结果保存图片再放到doc文档中,尤其是一些统计性质的结果,反复粘贴只会让人对工作产生厌烦情绪;
保证结果可重复:其实在我们做研究的过程中,总会遇到无法复现出别人的实验结果,无法获得跟原文作者或者实验室师兄师姐的实验效果,产生这种问题的情况有很多,最普遍的是学术不端,为了防止此类事情的发生,自动化报告就可以派上用场了。
对于knitr的创立,还是源于对sweave复杂使用的改进,这些编程范式最主要的目的是把实验代码和论文正文放到一起,编译的时候可以直接执行代码,并将结果保存在正文所需要的位置。这种方法统称为文学化编程(Literate Programming),这个名字很有文艺范,让我突然有种想成为一个仰望云端的文艺男青年的赶脚~
这种设计方式的优势显而易见:代码和文档在一起,方便互相更新和照应。比如修改了代码之后可以很快也更新相应的文档段落,而不必像传统方式那样,从源代码文件跳到文档文件中去更新。
对于knitr名字的来源,谢老大是这样描述link的:
knitr这个包的名字是怎么来的呢?Sweave实际上是由S(代表S语言,也就是R语言它娘亲)和weave(编织)组成的,Weave是文学化编程的概念,就是把文字和代码编织到一起。我在考虑包的名字的时候,由于满心要对Sweave的各种不利索吐槽,所以我决定给我的新包一个利索的名字,英语里说利索通常用neat这个词,而同时编织还有另一个词叫knit,二者发音相近,用它取名可谓一石二鸟,音意两全。knit后面加上字母r也有几重考虑:
1.R代表R语言,为什么小写?因为小写对用户来说输入方便,不用按Shift;
2.knitr看起来和读起来像knitter,谐音neater,充分表达了某种要凌驾于对手之上的情绪,说得不好听就是自恋;
3.knitr不是一个正常的英文单词,所以Google搜索的第一条确定一定以及肯定会是我的网站,方便用户搜到文档,在各种社交网络上它也可以作为标签。
knitr可以很方便的生成报告是因为采用markdown的编程范式,对于markdown的使用可以参考我之前的文档link,也可参考另一篇中文的MarkDown语法说明link。knitr已经包含代码高亮,所以就不需要采用我介绍的那种代码高亮的方式。
同样,knitr支持Latex
,如果你试过一次Latex
,你就会爱上她,很简单,比word输入公式简单好几条街。对于Latex的使用说明可以自行学习,参考Latex数学公式对照表以及Mathjax公式简介。我们可以在实验报告中输入类似以下的公式,并使公式左对齐:
\[ \begin{align} MISE & = E[ISE]\\\ & = E[\int(\hat{f}(x)-f(x))^2dx] \\\ & = \int E[(\hat{f}(x)-f(x))^2]dx \\\ & = \int MSE(\hat{f}(x)) \\\ & := IMSE \end{align} \]
我们还可以通过直接写HTML代码控制字体大小或者颜色等样式,也可将格式封装到CSS中。例如输入drafly是谁?:
<p>
<font size="5" face="Verdana" color="color-value">
drafly是谁?
</font>
</p>
drafly是谁?
knitr的配置很简单,具体参考knitr的主页。主要步骤如下:
安装knitr包;
配置knitr:将Preference -> Sweave -> Weave Rnw files using 改为 knitr;
新建文件 -> New File -> R Markdown,选择要生成文件格式HTML;
点击Knit HTML按键即可生成对应的研究报告。
在Rmd文件中添加代码段(Insert Chunks),如下:
## ----cool, results='asis'------------------------------------------------
library(knitr)
summary(head(mtcars))
## mpg cyl disp hp
## Min. :18.10 Min. :4 Min. :108.0 Min. : 93.0
## 1st Qu.:19.27 1st Qu.:6 1st Qu.:160.0 1st Qu.:106.2
## Median :21.00 Median :6 Median :192.5 Median :110.0
## Mean :20.50 Mean :6 Mean :211.8 Mean :117.2
## 3rd Qu.:21.30 3rd Qu.:6 3rd Qu.:249.8 3rd Qu.:110.0
## Max. :22.80 Max. :8 Max. :360.0 Max. :175.0
## drat wt qsec vs
## Min. :2.760 Min. :2.320 Min. :16.46 Min. :0.0
## 1st Qu.:3.098 1st Qu.:2.684 1st Qu.:17.02 1st Qu.:0.0
## Median :3.500 Median :3.045 Median :17.82 Median :0.5
## Mean :3.440 Mean :2.988 Mean :18.13 Mean :0.5
## 3rd Qu.:3.888 3rd Qu.:3.384 3rd Qu.:19.23 3rd Qu.:1.0
## Max. :3.900 Max. :3.460 Max. :20.22 Max. :1.0
## am gear carb
## Min. :0.0 Min. :3.0 Min. :1.000
## 1st Qu.:0.0 1st Qu.:3.0 1st Qu.:1.000
## Median :0.5 Median :3.5 Median :1.500
## Mean :0.5 Mean :3.5 Mean :2.167
## 3rd Qu.:1.0 3rd Qu.:4.0 3rd Qu.:3.500
## Max. :1.0 Max. :4.0 Max. :4.000
plot(cars)
可以看到knitr可以执行上述的代码段,并绘制图表。在代码段中我们还可以通过参数控制代码段。例如:
代码高亮(highlight=TRUE),增强可读性,有无数的高亮主题可选,仅适用于LaTeX和HTML输出,MD文档在转为HTML文档之后可以用专门的JavaScript库去高亮代码;
代码重排(tidy=TRUE),对那些不注意代码格式的人来说很有用,再乱的代码,到了这里也会变得相对整齐,本功能由formatR包支持;
执行或不执行代码(eval=TRUE/FALSE),不执行的代码段将被跳过,原样输出源代码;
显示/隐藏源代码(echo=TRUE/FALSE),甚至精确控制显示哪几段代码(echo取数值);
显示/隐藏普通文本输出或将文本输出以原样形式输出(results=‘markup’, ‘hide’, ‘asis’);
显示/隐藏警告文本(warning=TRUE/FALSE)、错误消息(error)和普通消息(message);
显示/隐藏整个代码段的输出(include=TRUE/FALSE),比如我们可能想运行代码,但不把结果写入输出中。
但是从上面的结果可以看出R的表格不太美观,这里可以采用ktable封装knitr的表格。
## ----cool, results='asis'------------------------------------------------
library(knitr)
kable(head(mtcars))
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
Hornet Sportabout | 18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
Valiant | 18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
或者采用JQuery的dataTable来封装表格,dataTable功能相对更强大一些。有很多参数可供选择,比如,搜索、排序、翻页等。具体参考DataTables官网。
## ----cool, results='asis'------------------------------------------------
library(knitr)
kable(head(mtcars), 'html', table.attr='id="mtcars_table"')
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
Hornet Sportabout | 18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
Valiant | 18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
–>
需要注意的是,想要生成该表格,还需要在代码段外添加如下js代码:
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.7/css/jquery.dataTables.css">
<!-- jQuery -->
<script type="text/javascript" charset="utf8" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<!-- DataTables -->
<script type="text/javascript" charset="utf8" src="http://cdn.datatables.net/1.10.7/js/jquery.dataTables.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#mtcars_table').DataTable({"bJQueryUI": false});
} );
</script>
如果CDN方式访问不便的话,可以将该包下载到本地Downloads,访问方式如下:
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="./DataTables-1.10.7/media/css/jquery.dataTables.css">
<!-- jQuery -->
<script type="text/javascript" charset="utf8" src="./DataTables-1.10.7/media/js/jquery.js"></script>
<!-- DataTables -->
<script type="text/javascript" charset="utf8" src="./DataTables-1.10.7/media/js/jquery.dataTables.js"></script>
knitr可用于实验室小组交流和毕业原型系统的制作,相比与原有C++编写的系统而言,更为简洁有效,同时,生成HTML格式文件在任何操作系统的计算机均可使用、查阅,可扩展性更强。