[原]文檔定義應用:數據科學的文檔革命

概述

隨着近年來,Rstudio 經過 shiny 將R語言推向Web化,Rmarkdown 藉助 Shiny 已經不斷演化造成了一個動態可交互文檔生態。對於數據科學的研究能夠說已是Every Thing in Rmd!本文我將介紹Rmd如何以文檔定義應用的方式(Docs As an App)成爲數據科學中的標準交付。css

clipboard.png

什麼是Rmd

Rmd 是Rmarkdown的文件保存格式,而Rmarkdown 是一個由謝益輝老師(XRAN)十年磨一劍的動態可重複文檔解決方案。參考前文:基於RStudio Webinars的統計報告Web化與工程化實踐總結,咱們能夠知道,Rmarkdown緣起謝大大對LaTex論文寫做的深惡痛絕,在謝大大深刻研究各類姿式的論文撰寫方式後決定自成一派,因而推出了Rmarkdown極大地簡化了論文寫做的排版問題並快速成爲了學界的論文寫做新標準。html

借用謝大大的例子,你能夠運行下面的代碼來生成一個pdf的beamer。前端

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

bib

yaml中能夠指定bibliography的路徑來解決引用文獻的問題。python

---
title: "Sample Document"
output: html_document
bibliography: bibliography.bib
---

這裏的引用咱們能夠很容易在Google Scholar生成,固然,除了BibTeX,Rmd 也支持 EndNote,RefMan,RefWorks以及直接在yaml中的引用方式。git

---
references:
- id: fenner2012a
  title: One-click science marketing
  author:
  - family: Fenner
    given: Martin
  container-title: Nature Materials
  volume: 11
  URL: 'http://dx.doi.org/10.1038/nmat3283'
  DOI: 10.1038/nmat3283
  issue: 4
  publisher: Nature Publishing Group
  page: 261-263
  type: article-journal
  issued:
    year: 2012
    month: 3
---

Rmd 原理分析

若是有用過APIDoc或者Swagger這樣的API文檔撰寫工具,或者利用Jekyll(Ruby)、Hexo(JS)、Pelican(Python)搭建我的網站的開發者應該很容易就明白,Rmarkdown的原理和這些應用很是相似。github

靜態渲染

首先,咱們利用markdown事先聲明好必定的文檔格式。其次,利用文檔解析器對markdown中的內容和dom樹作解析。最後,再用相應的css、js作渲染生成h5頁面,這樣一個文檔定義應用的過程就完成了。web

動態渲染

而文檔的動態化則是用一個後端服務器來host這些前端html頁面資源。這裏Rmarkdown能夠利用Shiny-server做爲後端服務器,在運行前端h5頁面的同時經過後端的服務器作實時的數據處理,實現文檔的動態化。(在文章最後會舉一些相應的例子)編程

注意,這裏若是在shiny-server的相關目錄下同時存在shiny的app.R文件,shiny-server將會優先識別app.R而不是.Rmd。json

想要動手嘗試的同窗能夠參考前文:打造數據產品的快速原型:Shiny的Docker之旅segmentfault

數據科學與 Rmd

首先,參考前文:數據科學部門如何使用Python和R組合完成任務,讓咱們來回顧一下以前談到了數據科學理論上會經歷的幾個階段:

需求定義=》數據收集=》數據轉化=》數據分析=》數據可視化

而在需求快速變化的項目初期,爲了快速肯定需求,如何敏捷打造最小可用原型(MVP)顯然比項目工程化來得更有意義。

因此在現實中,這時候流程經常就會縮短成:

需求定義=》數據整理=》數據可視化

場景一:需求分析多格式文檔交付

需求定義階段,咱們須要經過大量的Email、word、paper、keynote、訪談等等資料針對相關的業務場景進行初步瞭解,這一階段咱們最大的需求不是着急碼代碼,而是在起跑以前看準方向,繫好鞋帶,弄明白真實的業務需求,對實際需求進行優先級排序(作什麼)。

在需求定義階段,每次訪談、實地考察、活動會議等等都須要咱們產出相應的研究紀錄。通過來來回回的幾輪討論,咱們還須要畫不少流程圖、示意圖等等,最後產出一份完整的產品需求分析報告(爲何作)和產品需求文檔(怎麼作)。

在這個過程當中,不少細節都須要反覆推敲,多方論證(撕逼),而這個環節也是數據科學最有趣的一環。

面對大量的文檔輸出,不少人跟我同樣都會首先想到馬克飛象。馬克飛象名聲在外,是很優秀的一款產品。不過對於文檔的同步目前是收費的服務,很惋惜,由於預算有限,因此我仍是沒有考慮它,暫時是經過svn/git的方式解決雲端同步的問題。

參考前文:解密Airbnb的數據科學部門若是構建知識倉庫,做爲一個謝大大的死忠,我很天然選擇了 Rmarkdown 做爲我文檔輸出的首選工具。一方面,我不只能夠方便地嵌入本地或者網絡上的圖片,經過'[@]'語法也能夠利用yaml中的信息直接引用相關的參考文獻。另外一方面,在網絡狀況很是糟糕的狀況下,我也沒必要擔憂經過Web編輯沒法編輯的問題,而全部的編輯結果都會被存放在Rstudio的.Rdata文件中,實現和Web編輯器相似的實時編輯功能。

經過設置本身喜歡的css樣式,我還能夠個性化導出html文檔,統一輸出團隊的VI系統,這方面Airbnb是一個很好的榜樣,咱們能夠參考前文:解密Airbnb的數據科學部門如何使用R語言。你也能夠參考V2EX裏你們對於Markdown樣式的熱烈討論

在需求報告的討論環節,在yaml中簡單聲明shiny的runtime,再將Rmd文檔上傳到shiny-server上就能夠在網絡上(內網或外網)多人多端同步瀏覽,在Mac找不到轉化頭作投影的時候很是有用。

---
title: "文檔定義應用:數據科學 Everything in Rmd"
author: "Harry Zhu"
date: "May 13, 2016"
output: html_document
runtime: shiny
---

更爲實用的是,若是須要評審修改文檔,咱們也能夠導出word來互相評審修改,咱們甚至還能直接導出目錄,徹底不須要本身再手動生成目錄。

option

在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官網

場景三:數據產品敏捷響應

數據科學部門在推動項目的過程當中若是隻是拿着一些示意圖和文檔就去和各個部門討論而沒有拿出實際可用的產品必然會出現幾個問題:

  1. 交流低效。對產品和需求的理解停留在紙面,每每多方反覆溝通後對產品依賴概念模糊。

  2. 信心不足。當咱們沒有拿出實際可用的產品,項目戰線上的成員對項目的承認度比較低,各自相應的投入也就不會太多。

衆所周知,數據可視化是R很是擅長的領域。得益於R語言社區大量開發者對大量JS做圖框架熱情洋溢的封裝,咱們能夠利用R接口調用諸如echats、highcharts、leaflet、datatable這樣的前端組件,輕鬆完成數據產品的快速原型。

如今經過shinydashoboardflexdashboard,咱們能夠快速開始數據產品的原型構建,而這一切均可以輕鬆集成在一個.Rmd文件中。

shinydashboard

shinydashboard官網 Demo: https://gallery.shinyapps.io/...

GitHub源碼地址:https://github.com/rstudio/sh...

這裏你能夠執行運行示例。

# 安裝依賴
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")


引用官網的另一個例子,固然你也能夠在Rmd中直接省去定義ui和server的步驟,寫成這樣:

---
title: "something"
author: "Harry Zhu"
date: "May 13, 2016"
output: html_document
runtime: shiny
---

library(shinydashboard)
dashboardBody(
    tabItems(
      # 第一個tab
      tabItem(tabName = "dashboard",
        fluidRow(
          box(plotOutput("plot1", height = 250)),

          box(
            title = "Controls",
            sliderInput("slider", "Number of observations:", 1, 100, 50)
          )
        )
      ),

      # 第二個tab
      tabItem(tabName = "widgets",
        h2("Widgets tab content")
      )
    )
  )
# 直接在後面定義做圖函數
set.seed(122)
  histdata <- rnorm(500)

  output$plot1 <- renderPlot({
    data <- histdata[seq_len(input$slider)]
    hist(data)
  })

省去的ui和server的定義,直接渲染Rmd。

flexdashboard

flexdashboard Demo: https://beta.rstudioconnect.c...

sales report

開源源碼以下:

```
---
title: "Sales Report with Highcharter"
author: "Joshua Kunst"
output:
flexdashboard::flex_dashboard:

orientation: columns
social: menu
source_code: embed

---
```
```{r setup, include=FALSE}
library(highcharter)
library(dplyr)
library(viridisLite)
library(forecast)
library(treemap)
library(flexdashboard)

thm <-
hc_theme(

colors = c("#1a6ecc", "#434348", "#90ed7d"),
chart = list(
  backgroundColor = "transparent",
  style = list(fontFamily = "Source Sans Pro")
),
xAxis = list(
  gridLineWidth = 1
)

)

```

Column {data-width=600}
-----------------------------------------------------------------------

### Sales Forecast

```{r}
AirPassengers %>%
forecast(level = 90) %>%
hchart() %>%
hc_add_theme(thm)
```

### Sales by State

```{r}
data("USArrests", package = "datasets")
data("usgeojson")

USArrests <- USArrests %>%
mutate(state = rownames(.))

n <- 4
colstops <- data.frame(
q = 0:n/n,
c = substring(viridis(n + 1), 0, 7)) %>%
list.parse2()

highchart() %>%
hc_add_series_map(usgeojson, USArrests, name = "Sales",

value = "Murder", joinBy = c("woename", "state"),
                dataLabels = list(enabled = TRUE,
                                  format = '{point.properties.postalcode}')) %>%

hc_colorAxis(stops = colstops) %>%
hc_legend(valueDecimals = 0, valueSuffix = "%") %>%
hc_mapNavigation(enabled = TRUE) %>%
hc_add_theme(thm)
```

Column {.tabset data-width=400}
-----------------------------------------------------------------------

### Sales by Category

data("Groceries", package = "arules")
dfitems <- tbl_df(Groceries@itemInfo)

set.seed(10)

dfitemsg <- dfitems %>%
  mutate(category = gsub(" ", "-", level1),
         subcategory = gsub(" ", "-", level2)) %>%
  group_by(category, subcategory) %>% 
  summarise(sales = n() ^ 3 ) %>% 
  ungroup() %>% 
  sample_n(31)

tm <- treemap(dfitemsg, index = c("category", "subcategory"),
              vSize = "sales", vColor = "sales",
              type = "value", palette = rev(viridis(6)))

highchart() %>% 
  hc_add_series_treemap(tm, allowDrillToNode = TRUE,
                        layoutAlgorithm = "squarified") %>% 
  hc_add_theme(thm)

### Best Sellers

```{r}
set.seed(2)

nprods <- 10

dfitems %>%
sample_n(nprods) %>%
.$labels %>%
rep(times = sort(sample( 1e4:2e4, size = nprods), decreasing = TRUE)) %>%
factor(levels = unique(.)) %>%
hchart(showInLegend = FALSE, name = "Sales", pointWidth = 10) %>%
hc_add_theme(thm) %>%
hc_chart(type = "bar")

```

咱們能夠看到這裏的排版方式被大大的簡化了,咱們只須要定義好Column和Row,而後在相應的代碼塊裏盡情的做圖就能夠在前端頁面上可視化了,相比之下css真是操碎了心。

rowpng

更多關於flexdashboard的高級技巧能夠前往flexdashboard官網

echarts

因爲你們對echarts的呼聲很高,這裏再演示一下echart在R中的調用。

# 下載包
install.packages(
  'recharts',
  repos = c('http://yihui.name/xran', 'http://cran.rstudio.com')
)
# 畫圖
recharts::echart(iris, ~Sepal.Length, ~Sepal.Width, series = ~Species)

echarts

另一個牛逼的功能是,經過REmap這個包(已經封裝了各類百度API),咱們能夠將物流的收貨地址直接輸入沒必要太規則的中文文本便可實現地圖數據的可視化。並且,最近特別火的莆田系醫院數據爬取及分佈可視化大多也是經過REmap包實現的。

更多echarts的做圖這裏不一一介紹,高級技巧能夠前往recharts官網或者SupStat 郎大爲:REmap

Notebook

根據雪晴數據網的最新消息,RStudio 也已經實現了相似iPython的Notebook功能。

下面是雪晴數據網的教程

配置步驟

  1. 下載最新的RStudio每日版

  2. 下載最新版本的Rmarkdown包:

devtools::install_github("rstudio/rmarkdown")
  1. 設置選項:Tools -> Global Options -> Rmarkdown -> Enable R Notebook -> Apply

  2. 像往常同樣打開一個新的Rmarkdown文件

  3. 設置YAML輸出選項:將output: html_document 改成 output: html_notebook: default

Rmd + Docker = liftr

liftr 視頻教程

躺坑排雷

在安裝最新版本後,因爲個人鏡像源設成了 MRAN,致使這裏更新的 evaluateknitr包的版本太低須要指定CRAN源從新升級。

> getOption("repos")
                                                      CRAN 
"https://mran.revolutionanalytics.com/snapshot/2015-08-27"
install.packages(c("evaluate","knitr"),repos="http://mirror.bjtu.edu.cn/cran/")

Notebook API

經過 Notebook API,咱們還能夠把任意的Rmd文檔輸出成Notebook。

rmarkdown::render("FinanceR.Rmd",out_format="html_notebook")
notebook <- parse_html_notebook("FinanceR.nb.html")

參考資料

推薦工具

文末,推薦一款相似於 Airbnb 用 Flask 生成博客的解決方案,能夠有效在團隊內部作知識倉庫的共享:

比較惋惜的是,我嘗試了多個 Leanote 的Docker方案都沒有成功,若是讀者有成功案例歡迎在留言區留言。

另外,還推薦一個相似於 Endnote 的論文神器:

利用 Zotero 咱們能夠輕鬆的經過 drap and drop 實現多人協同論文跟蹤管理的功能,而且支持Chrome插件、多平臺客戶端。

做爲分享主義者(sharism),本人全部互聯網發佈的圖文均聽從CC版權,轉載請保留做者信息並註明做者 Harry Zhu 的 FinanceR專欄:https://segmentfault.com/blog...,若是涉及源代碼請註明GitHub地址:https://github.com/harryprince。微信號: harryzhustudio商業使用請聯繫做者。

相關文章
相關標籤/搜索