Shiny 入門
林茂廷老師
2017-12-13
第 1 章 Shiny Part I
背景知識
以An Introduction to R為參考書,完成此課程你必需對以下知識有「基本」了解(只要基本就好):
- 如何在R裡寫function (Chapter 10)
- 如何在R裡做基本的繪圖 (Chapter 12)
- 理解R裡的列串(list)變數特質 (Chapter 6)
壹:簡介
Shiny套件能夠幫助你快速地建立一個互動式網頁,不需要擔心不懂網頁語言。
互動網頁基本上是透過使用者介面(user interface, ui),這裡是網頁瀏覽器,讓使用者輸入參數。這些參數會送到電腦運算,運算完的結果會再傳回到ui讓使用者看。這裡的電腦可以是個人主機或雲端主機,統稱為伺服器server——「伺服」的意思是「伺機」在旁等候呼叫「服務」的意思,所以這個電腦是隨時在注意ui有沒有動作。很明顯的ui會產生input,而server會產生output然後放回ui讓使用者看到結果。
壹-1: ui設計概念
Shiny的ui設計即為網頁設計,而網頁設計時頁面的物件位置有固定位置(Fixed)與流動位置(Fluid)兩大類(混用的則稱為Elastic)——後者比較不會因為每個人螢幕的尺寸不同而產生頁面扭曲、物件錯置;Shiny採流動佈局(Fluid layout)來定義ui上各物件呈現的位置。
以下是基本ui程式元素
ui<-fluidPage(...)
Shiny透過fluidPage()
產生流動位置佈局的網頁程式碼,R使用者並不太需要會寫網頁程式。
另外,前面我們說過ui必需要能讓使用者輸入input,且能讓server放回output,故完整ui程式元素如下:
ui<-fluidPage(
#1. 整體網頁佈局設計
#2. Input佈局設計
#3. Output佈局設計
)
其中2會產生一個input串列變數,裡頭包含了使用者要的參數設定;3會產生一個圖表空間保留給output串列變數呈現用,同時output串列變數的元素名稱也會在此定義好(只有名稱,沒有內容)。output串列內各元素的內容需要接下來的server,依input參數去產生參數對應圖表物件回填,之後output的圖表內容才會呈現在ui保留的output空間。
想多了解流動佈局:
- W3.CSS Responsive Fluid Grid
壹-2: server服務內容
server基本上會去接收ui的input,從input得到參數後,進行計算產生圖表填回去準備好的output串列元素中。
server程式元素如下:
server<-function(input,output){
#從input得到參數後,進行計算產生圖表填回去output的程式
}
ui與server關聯圖
壹-3: 啟動shinyApp
前面兩小節定義好ui及server內容,現在你只需要Shiny幫你把你的R程式轉成網頁語言。透過shinyApp()
指令,你可以立刻在你電腦看到動態網頁的成品。
執行以下指令立刻在電腦上使用互動網頁成品:
shinyApp(ui=ui,server=server)
貳:UI 流動佈局設計
首先要啟動shiny套件:
library(shiny)
這節我們進入細部ui流動佈局設計部份,參考資料為:
流動UI佈局裡,頁面設計主要有sidebarLayout()
與FluidRow()
兩大類,以下為圖例:
- sidebarLayout() 圖例
sidebarLayout的UI圖面包含圖形主區塊(main)及使用者輸入的側邊區塊(sidebar),側邊區塊UI input部份(即圖例上的拉把)只能在左或右。
- FluidRow() 圖例
較有彈性的調整,但比sidebarLayout複雜。以下我們以sidebarLayout為開始練習。
參:Server運算函數
依據定義,下圖表示範例中ui-server間的互動:
由圖中,我們知道server function會運作如下:
server <- function(input,output){
output$number.selected <- {一堆程式列,可使用input$income.levels參數, 來產生東西}
}
之前input$income.levels
誤植成input$number.selected
Shiny的server回存部份 (即這裡的output$number.selected <-
)依ui-mainPanel()裡所使用的UI output函數不同而不同。在server函數裡回存函數稱為Rendering functions,可參見reference裡的Rendering functions部份:
依據同樣reference裡對UI inputs::textOutput裡的Details說明,我們會使用Rendering functions::renderText函數。
範例三:
將
input$income.levels
的結果以文字方式存在output$number.selected
裡。
在過去如果只是直接把input$income.levels
要存在output$number.selected
,我們只需要寫:
output$number.selected <- input$income.levels
但依Shiny使用方式,我們必需要透過renderText()
函數,使用法為:
output$number.selected <- renderText(
{
產生output$selected所需要的所有程式列
}
)
這裡需要的程式列只有 input$income.levels一行,所以server函數會寫成如下:
server <- function(input, output) {
output$number.selected <- renderText(
{
input$income.levels
}
)
}
肆:啟動完整UI-Server應用程式
一旦ui函數及server函數都設定完後,使用下列程式執行此互動網頁應用程式:
shinyApp(ui=ui,server=server)
這個簡單的Shiny範例其實相當好用,可用來檢查UI input是否真的產生我們想要的input形式與內容給server,即使server需要做的是繪圖,但先檢查所需繪圖參數是否是你要的形式,可以減少之後的繪圖錯誤。
課後練習
請由Widgets gallery設計一個UI-sidebarLayout介面, 在sidebarPanel部份包含Date range用來設定住宿起迄日期及Slider range用來設定可接受平均每晚房價(千元)範圍,之後server函數會回傳UI-mainPanel文字結果,顯示輸入結果。 完成練習後,請以此檔名再加你的名字送出pull request。 [hint: sidebarPanel裡可以加不只一個UI input,只要用逗號分隔好就好]
使用Part I HW.Rmd完成練習後上傳到Dropbox作業匣
Reference
Shiny reference
- See UI inputs and UI outputs for UI layout