随着近年来,Rstudio 通过 shiny 将R语言推向Web化,Rmarkdown 借助 Shiny 已经不断演化形成了一个动态可交互文档生态。对于数据科学的研究可以说已经是Every Thing in Rmd!本文我将介绍Rmd如何以文档定义应用的方式(Docs As an App)成为数据科学中的标准交付。
Rmd 是Rmarkdown的文件保存格式,而Rmarkdown 是一个由谢益辉老师(XRAN)十年磨一剑的动态可重复文档解决方案。 参考前文:基于RStudio Webinars的统计报告Web化与工程化实践总结 ,我们可以知道,Rmarkdown缘起谢大大对LaTex论文写作的深恶痛绝,在谢大大深入研究各种姿势的论文撰写方式后决定自成一派,于是推出了Rmarkdown极大地简化了论文写作的排版问题并快速成为了学界的论文写作新标准。
download.file("https://raw.githubusercontent.com/rstudio/webinars/master/13-R-Markdown-Ecosystem/presentation.Rmd",destfile = "presentation.Rmd") # 下载Rmd文件 download.file("https://raw.githubusercontent.com/rstudio/webinars/master/13-R-Markdown-Ecosystem/references.bib",destfile = "references.bib") # 下载bib引用 rmarkdown::render("presentation.Rmd", rmarkdown::pdf_document()) # 生成pdf
这里的引用我们可以很容易在Google Scholar生成,当然,除了BibTeX,Rmd 也支持 EndNote,RefMan,RefWorks以及直接在yaml中的引用方式。
如果有用过APIDoc或者Swagger这样的API文档撰写工具,或者利用Jekyll(Ruby)、Hexo(JS)、Pelican(Python)搭建个人网站的开发者应该很容易就明白,Rmarkdown的原理和这些应用非常类似。
首先,我们利用markdown事先声明好一定的文档格式。其次,利用文档解析器对markdown中的内容和dom树做解析。最后,再用相应的css、js做渲染生成h5页面,这样一个文档定义应用的过程就完成了。
而文档的动态化则是用一个后端服务器来host这些前端html页面资源。这里Rmarkdown可以利用Shiny-server作为后端服务器,在运行前端h5页面的同时通过后端的服务器做实时的数据处理,实现文档的动态化。(在文章最后会举一些相应的例子)
注意,这里如果在shiny-server的相关目录下同时存在shiny的app.R文件,shiny-server将会优先识别app.R而不是.Rmd。
想要动手尝试的同学可以 参考前文:打造数据产品的快速原型:Shiny的Docker之旅 。
首先, 参考前文:数据科学部门如何使用Python和R组合完成任务 ,让我们来回顾一下之前谈到了数据科学理论上会经历的几个阶段:
需求定义=》数据收集=》数据转化=》数据分析=》数据可视化
而在需求快速变化的项目初期,为了快速确定需求,如何敏捷打造最小可用原型(MVP)显然比项目工程化来得更有意义。
所以在现实中,这时候流程常常就会缩短成:
需求定义=》数据整理=》数据可视化
需求定义阶段,我们需要通过大量的Email、word、paper、keynote、访谈等等资料针对相关的业务场景进行初步了解,这一阶段我们最大的需求不是着急码代码,而是在起跑之前看准方向,系好鞋带,弄明白真实的业务需求,对实际需求进行优先级排序(做什么)。
在需求定义阶段,每次访谈、实地考察、活动会议等等都需要我们产出相应的研究纪录。经过来来回回的几轮讨论,我们还需要画很多流程图、示意图等等,最后产出一份完整的产品需求分析报告(为什么做)和产品需求文档(怎么做)。
在这个过程中,很多细节都需要反复推敲,多方论证(撕逼),而这个环节也是数据科学最有趣的一环。
面对大量的文档输出,很多人跟我一样都会首先想到马克飞象。马克飞象名声在外,是很优秀的一款产品。不过对于文档的同步目前是收费的服务,很可惜,因为预算有限,所以我还是没有考虑它,暂时是通过svn/git的方式解决云端同步的问题。
参考前文:解密Airbnb的数据科学部门如果构建知识仓库 ,作为一个谢大大的死忠,我很自然选择了 Rmarkdown 作为我文档输出的首选工具。一方面,我不仅可以方便地嵌入本地或者网络上的图片,通过'[@]'语法也可以利用yaml中的信息直接引用相关的参考文献。另一方面,在网络情况非常糟糕的情况下,我也不必担心通过Web编辑无法编辑的问题,而所有的编辑结果都会被存放在Rstudio的.Rdata文件中,实现和Web编辑器类似的实时编辑功能。
通过设置自己喜欢的css样式,我还可以个性化导出html文档,统一输出团队的VI系统,这方面我们可以 参考前文:解密Airbnb的数据科学部门如何使用R语言 。
在需求报告的讨论环节,在yaml中简单声明shiny的runtime,再将Rmd文档上传到shiny-server上就可以在网络上(内网或外网)多人多端同步浏览,在Mac找不到转化头做投影的时候非常有用。
--- title: "文档定义应用:数据科学 Everything in Rmd" author: "Harry Zhu" date: "May 13, 2016" output: html_document runtime: shiny ---
更为实用的是,如果需要评审修改文档,我们也可以导出word来互相评审修改,我们甚至还能直接导出目录,完全不需要自己再手动生成目录。
在word和html之间自由切换,进可审阅、退可编辑,显然,在现实中我们没法决定我们身边的人是喜欢word还是喜欢html。
当然,除了html和word,Rmd还可以在多种酷炫的keynote、dashboard、pdf之间相互转化,不过这里由于篇幅有限暂时不展开讨论。
更多高级的Rmarkdown文档转换技巧可以前往 rmarkdown官网
之所以说原来 数据收集=》数据转化=》数据分析 的流程可以简化为数据整理主要是因为这里数据源获取的方式一般比较dirty,比如从一个Excel的 xlsx文件读取、通过现场勘查记录自己制作的临时数据又或者通过Python爬虫抓取的一部分数据、从某些文章中直接复制粘贴的数据等等。而处理这些dirty的数据往往都会采用比较crud的方式,并不会做非常详细的分析工作(很多公司的数据分析实习生工作都是从这里起步的)。
在数据整理的过程中,我们可能会用到多种编程语言或者工具(比如Python、R、awk)、多种文件格式(比如csv、xlsx、json、pdf、word),这时候为了兼容多种工具并保证研究的可重复性,我们非常需要在一个文档中运行多种编程语言。
通过knitr的代码块管理,我们可以轻松选择代码编译环境来兼容多种编程语言,比如这样:
```{python}
x = 'hello, python world!'
print(x)
print(x.split(' '))
import matplotlib.pyplot as plt
plt.plot(range(10))
plt.show()
```
当然我们也可以自定义代码编译引擎:
> system("which python") # 查到 python 引擎的默认路径 /Users/harryzhu/Library/Enthought/Canopy_64bit/User/bin/python
进一步定义 python 引擎的路径:
```{r engine=python,engine.path='/Users/harryzhu/Library/Enthought/Canopy_64bit/User/bin/python'}
x = 'hello, python world!'
print(x)
print(x.split(' '))
import matplotlib.pyplot as plt
plt.plot(range(10))
plt.show()
```
更多高级的knitr代码块使用技巧可以移步谢大大的 knitr官网
数据科学部门在推进项目的过程中如果只是拿着一些示意图和文档就去和各个部门讨论而没有拿出实际可用的产品必然会出现几个问题:
交流低效。对产品和需求的理解停留在纸面,往往多方反复沟通后对产品依赖概念模糊。
信心不足。当我们没有拿出实际可用的产品,项目战线上的成员对项目的认可度比较低,各自相应的投入也就不会太多。
众所周知,数据可视化是R非常擅长的领域。得益于R语言社区大量开发者对大量JS作图框架热情洋溢的封装,我们可以利用R接口调用诸如echats、highcharts、leaflet、datatable这样的前端组件,轻松完成数据产品的快速原型。
现在通过 shinydashoboard 、 flexdashboard ,我们可以快速开始数据产品的原型构建,而这一切都可以轻松集成在一个.Rmd文件中。
shinydashboard官网 Demo: https://gallery.shinyapps.io/087-crandash/
GitHub源码地址: https://github.com/rstudio/shiny-examples/tree/master/087-crandash
# 安装依赖 install.packages(c("shiny", "dplyr", "htmlwidgets", "digest", "bit")) devtools::install_github("rstudio/shinydashboard") devtools::install_github("jcheng5/bubbles") devtools::install_github("hadley/shinySignals") # 运行 shiny::runGitHub("rstudio/shiny-examples",subdir = "087-crandash")
flexdashboard Demo: https://beta.rstudioconnect.com/jjallaire/htmlwidgets-highcharter/
R Markdown: Integrating A Reproducible Analysis Tool into Introductory Statistics