統計R語言實作筆記系列 – 用 Shiny 套件極速打造你的商業智慧分析網站!

早在 Big Data 一詞還未深入人心之前,商業智慧分析系統就已經在企業級應用領域有著長足的歷史,由國際知名的軟體公司設計的 Business Intelligence 產品的一貫傳統就是配上可以由客人自定義而且視覺化效果華麗的功能性圖表,又經常稱為企業儀表板 ( DashBoard ),能夠讓用戶根據不同的選項操作來從各種角度分析企業的即時經營數據。

而在以 R 為主要工具的資料科學社群中, Shiny 無疑是最佳的儀表板製作工具,它不但提供了免費版本,能讓你輕易地部署到網路上,而且也能搭配原先 R 就已經很強大的套件來執行資料重整、分析及繪圖,非常適合預算有限但需求殷切的企業用來打造屬於自己的 prototype 商業智慧系統。

在這篇教學文章當中,你將會學到如何用 R Shiny 快速實現這個目標。準備好了嗎?我們立刻開始吧!

別急著 Coding!先牛刀小試一下 Shiny 吧!

首先打開 R 編輯器,並輸入以下指令安裝 Shiny 套件:

install.packages(“shiny")

載入剛下載好的 Shiny 套件:

library(shiny)

由於 Shiny 套件包當中已經預先設計好了可以供初學者快速體驗的範例檔案,接著只要輸入:

runExample(“01_hello")

就會啟動範例程式,同時開啟頁面如下:

r-shiny-example

你一定很快就會注意到,在網頁左上方的資料條是可以捲動的,而且運算結果會即時反應在右方的圖表當中。

效果很不錯吧?

但 Shiny 可不只是如此而已,試試看以下的各種基本範例,你會對於 Shiny 的視覺效果有更明確的想像:

runExample(“02_text") # 資料表格

runExample(“03_reactivity") # 回應設計 + 資料表格

runExample(“04_mpg") # 繪圖

runExample(“05_sliders") # 側欄工具 + 表格

runExample(“06_tabsets") # tab 頁面

runExample(“07_widgets") # 行為按鈕

runExample(“08_html") # 結合 html

runExample(“09_upload") # 上傳檔案工具

runExample(“10_download") # 下載檔案工具

runExample(“11_timer") # 計時器

我們要如何透過 Shiny 來做到這些效果呢?

大致需要分成兩個部分來說,分別是負責控制網頁呈現的 ui.R 以及後端運算的 server.R 。

Shiny 的前端介面控制: ui.R

製作 ui.R ,你會需要新建一個 r script 檔案,接著命名為 ui.R 就行了。 同時 ui.R 的基本語法實在是短到不行:

shinyUI(

)

看起來很簡單吧?

不過當然光是只有這樣是不會產生任何頁面的,所以我們需要選擇一個「模板( layout )」,這個模板很大程度上將決定最終網頁的畫面呈現為何,在 Shiny 的官方教學中,選用的是 Tablets (對應 fluidPage 函數 )這個模板,在這裡筆者則刻意避開,改用 Navbar (對應 navbarPage 函數)模板,以便有興趣的讀者可以稍作比較,這樣很快就能掌握到 ui.R 的設計精隨了。

典型的 Navbar 設計在網頁上方會出現一排額外的選單,最終結果大概長得像這樣子:

r-shiny-navbar-example

這世界很少有一步登天的事情,寫程式也不例外,到我們能完成上方的範例之前還有一些工作要做。

首先,是在原本的 ui.R 程式碼中新增 navbar 語法,這裡請記得之後要新增在頁面上的小工具或其他功能都必須包在 navbar 底下才會符合預期的效果:

shinyUI(navbarPage(

))

在新增 navbar 後,頁面上已經產生一個區塊保留給導覽列,但是導覽列中還沒有任何東西可以進行點擊,因此我們需要新增幾個導覽列的選單按鈕。

在 navbar 中支援兩種類型的導覽列選單按鈕,一種是點擊後直接切換頁面的 tabPanel 以及可以允許按鈕中出現子選項的 navbarMenu 。

下方範例中同時實作兩個選單,同時進行必要的命名( Page Name、 Option1 、 Option2 ),你可以從比較中理解差異。

shinyUI(navbarPage(“Page Name",

tabPanel(“Option1″),

navbarMenu(“Option2″)

))

結果如下:

r-shiny-navbar-tutorial-1

由於被命名為 Option2 的 navbarMenu 需要子選單,因此我們需要調整程式碼,而子選單的按鈕元件,其實就是使用 tabPanel!

shinyUI(navbarPage(“Page Name",

tabPanel(“Option1″),

navbarMenu(“Option2″,
tabPanel(“Option2-1″),
tabPanel(“Option2-2″),
tabPanel(“Option2-3″))

))

成果如下圖:

r-shiny-navbar-tutorial-2

設計完了導覽列後,接著當然就是要把內容放進網頁裡去,在插入計算結果或者圖表之前,我們先試著放一些靜態的內容看看。

值得一提的是, Shiny 是支援 html 語法的,只需要經過一點點簡單的轉換,完成後接著把內容直接放在對應的元件區塊內並以「,」與前面的參數隔開就行了,詳見範例:

shinyUI(navbarPage(“Page Name",

tabPanel(“Option1″,
h1(“Hi, this is an example page")
),

navbarMenu(“Option2″,
tabPanel(“Option2-1″),
tabPanel(“Option2-2″),
tabPanel(“Option2-3″))

))

結果如下:

r-shiny-navbar-tutorial-3

如果你想要建構比較複雜的網頁樣式,那麼你除了基本的 UI 設計之外,最好也能夠大致了解一下 Shiny 在 UI 方面可以操作的幾大類型功能

  1. UI Layout
  2. UI Inputs
  3. UI Outputs
  4. Interface builder functions

Shiny 的後端資料運算: server.R

接著看到 server.R 的部分,基本框架類似於 ui.R 但多了 input 及 output 的參數:

shinyServer(function(input, output) {

})

既然 server.R 是負責處理運算,那麼讀取檔案也就是必要的步驟了,這裡讀取兩個 csv 資料集 Market_Price 以及 Products_Index ,並分別將資料變數命名為 MP 及 PI 。

請注意資料讀取一般是獨立在 shinyServer () 函式之外的。

MP<-read.csv(“Market_Price.csv",header=TRUE)

PI<-read.csv(“Products_Index.csv",header=TRUE)

shinyServer(function(input, output) {

output$exPlot<-renderPlot({

})

為了進行運算, shinyServer () 函式下加入的的每個功能函數都需要指定 input 物件,同時也會得到一組 output 物件,這很容易理解。

另一方面若是要動態配合用戶在前端 ui.R 的部分選取或輸入特定值的條件下改變運算結果,那麼也需要將前端的動作以對應 input 的方式傳入 server.R 內的運算式中,並把預設要儲存結果的 output 物件放於對應的 ui.R 位置上,才能達到這個效果。

聽起來有一點抽象,我們一步一步來。

首先知道 Shiny 支援什麼樣的運算結果呈現方式,對於後續進展會很有幫助:

  1. renderPlot # 圖形輸出
  2. renderText # 文字輸出
  3. renderPrint # 可印的結果輸出
  4. renderDataTable # 支援 Javascript library 的表格輸出
  5. renderImage # 圖檔輸出
  6. renderTable # 表格輸出
  7. renderUI # UI 物件輸出
  8. downloadHandler # 檔案下載功能

以最常見的 renderPlot 應用為例,它可以讓我們輸出 R 當中的圖形結果,植入 server.R 的語法如下。

這裡創造了兩個 output 變數: exPlot 及 exPlot2 ,同時以 ggplot 函式配合先前讀取的 MP 及 PI 資料變數作為 input 執行繪圖:

shinyServer(function(input, output) {

output$exPlot<-renderPlot({
ggplot(data=MP,aes(x=year,y=Gprice,fill=Cprice,xmax=100,ymax=100))+geom_bar(width=1,stat="identity")+ggtitle(expression(atop(“Market Analysis",atop(“")))) +theme(plot.title=element_text(size=20)) +theme_igray()+scale_colour_tableau()
}, height = 600, width = 900)

output$exPlot2<-renderPlot({
ggplot(data=PI,aes(x=Type,y=DemandIndex,fill=Type,xmax=100,ymax=100))+geom_bar(width=1,stat="identity")+coord_polar(theta = “x")+ggtitle(expression(atop(“Radar Analysis",atop(“let’s have fun"))))+theme(plot.title=element_text(size=20))+theme_igray()+scale_colour_tableau()
}, height = 600, width = 900)

})

讀者若是對於以上 ggplot 語法不太熟悉,其實可以直接忽略不看,不影響 Shiny 的使用,中間替換成任何你熟悉的繪圖套件語法都沒有問題,只要大約了解 renderPlot 是如何運作的,要依樣複製一個不是什麼難事。

假如你對於 R 的視覺化很有興趣,也歡迎繼續參閱作者的其他教學文章(見置底列表),此處不再贅述。

進行到這裡看起來也頗有進展了,不妨試試執行 runAPP 函式啟動你的 Shiny 程式:

runApp(“APP名稱即為放置 ui.R 及 server.R 的資料夾名稱")

整合 ui.R 及 server.R 的結果

假如你就這麼啟動了你的 APP ,大概會覺得很失望,怎麼沒有看到剛才 ggplot 的結果呢?

前面說到了, shinyServer () 函式需要一組 input,也會產生一組 output ,我們必須運用這個機制好讓結果可以透過 ui.R 呈現在網頁上,此例中對應 renderPlot 輸出的 output 函數為 plotOutput() 。

我們現在就要把 renderPlot 的結果變數 explot 與 explot2 利用 plotOutput 傳到 ui.R ,指定位置在分別被命名為的 Option1 以及 Option2-1 的兩個 tabPanel 內,詳見 ui.R 的語法如下:

shinyUI(navbarPage(“Page Name",

tabPanel(“Option1″,
h1(“Hi, this is an example page"),
plotOutput(“exPlot")
),

navbarMenu(“Option2″,
tabPanel(“Option2-1″,
plotOutput(“exPlot2″)),

tabPanel(“Option2-2″),
tabPanel(“Option2-3″))

))

現在當你點選 Option1 以及 Option2-1 的選單時,應該就可以看到你設計好的圖表華麗呈現了!

r-shiny-renderplot-tutorial-1

r-shiny-renderplot-tutorial-2

在辛苦製作完了一支精美的 Shiny 程式之後,你應該迫不及待想要分享給自己的同事或朋友吧?

在這邊文章的最後,就簡單說明一下你可以用來分享 Shiny 程式的幾種方法

  1. 將資料夾打包傳給對方,不過也需要下載 R 主程式及 Shiny 套件
  2. 打包成 zip 檔上傳網路,讓對方在 R 當中用  runUrl() 函式來執行
  3. 上傳 Github,讓對方在 R 當中使用 runGitHub () 函式來執行
  4. 弄一台 server 用來 host 你的 Shiny 程式,對方只要輸入公開的 url 就可以了

關於第 4 點 server 部署的部分,可以再細分為幾種途徑,例如依照指定規格自建一台 Shiny Server,或是使用 R Studio 公司提供的 Shiny Server Pro 、Shinyapps.io 服務,也是不錯的選擇。

更多 R 的攻略心得,繼續探索:

* 統計R語言實作筆記系列 – 2D視覺化進階 GGPLOT()的基本架構(一)

* 統計R語言實作筆記系列 – 2D視覺化入門

* 資料玩家人人必備! 5 分鐘快速部署你的第一支 R SHINY 互動式圖表網頁APP

* 統計R語言實作筆記系列- 直線ABLINE()、曲線CURVE()與多邊形POLYGON()

 

(Visited 38,357 times, 84 visits today)

Wendell.Huang

科技公司嫌棄太活潑,消費品牌挑剔太沉悶..., 經常必須解釋自己在學什麼, 不小心就摔破對方眼鏡的跨領域玩家。

5 Comments

  1. 感謝您的教學
    但是我在載入自己的data時出現錯誤
    請問您的兩個 csv 資料集 Market_Price 以及 Products_Index
    是否可提供呢

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *