Introduction about webApp writing by R

Chin Lin

Thursday, September 25, 2014

基本介紹

  1. 只需要連上網路即可使用

  2. 透過互動清楚的展示你所想表達的事物

  3. 對於使用者來說非常簡單上手

R語言

安裝套件

F0

在開始之前,先讓我們看看R語言能寫出什麼樣的App

開始創造一個簡單的App - Step 1

F1

開始創造一個簡單的App - Step 2

F2

開始創造一個簡單的App - Step 3

library(shiny)

# Define UI for application that plots random distributions 
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("Hello Shiny!"),

  # Sidebar with a slider input for number of observations
  sidebarPanel(
    sliderInput("obs", "Number of observations:", min = 0, max = 1000, value = 500)
  ),

  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))

F3

開始創造一個簡單的App - Step 4

library(shiny)

# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {

    # Expression that generates a plot of the distribution. The expression is
    # wrapped in a call to renderPlot to indicate that:
    # 
    # 1) It is 'reactive' and therefore should be automatically re-executed
    # when inputs change 2) Its output type is a plot
    output$distPlot = renderPlot({

        # generate an rnorm distribution and plot it
        dist = rnorm(input$obs)
        hist(dist)
    })

})

F4

開始創造一個簡單的App - Step 5

F5

F6

練習-1

簡單介紹Shinyapps

  1. 使用者自ui.R中的給定一個參數。

  2. 這個參數傳到server.R裡面,使用反應函數進行計算。

  3. 反應完成後,再回傳至ui.R輸出反應結果。

簡介ui.R內的參數

library(shiny)

# Define UI for application that plots random distributions 
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("Hello Shiny!"),

  # Sidebar with a slider input for number of observations
  sidebarPanel(
    sliderInput("obs", "Number of observations:", min = 0, max = 1000, value = 500)
  ),

  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))
  1. headerPanel()用來定義網頁標題

  2. sidebarPanel()用來定義的控制選單內含哪些可控參數,本例中只有一個滑動輸入元件sliderInput(),元件為obs

  3. mainPanle()則是用來定義輸出區域的輸出結果,本例中只有一個圖片輸出元件plotOutput(),元件為distPlot

F7

簡介server.R內的參數

library(shiny)

# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {

    # Expression that generates a plot of the distribution. The expression is
    # wrapped in a call to renderPlot to indicate that:
    # 
    # 1) It is 'reactive' and therefore should be automatically re-executed
    # when inputs change 2) Its output type is a plot
    output$distPlot = renderPlot({

        # generate an rnorm distribution and plot it
        dist = rnorm(input$obs)
        hist(dist)
    })

})

Note:所有的輸入元件都存取在input這個List內;而所有的輸出元件都存取在output這個List內。

學習R裡面的基本函數

        obs = 500
        M = 170
        S = 10
        Coler = "blue"
        dist = rnorm(obs,mean=M,sd=S)
        hist(dist,col=Coler)

plot of chunk unnamed-chunk-5

增加可控參數至剛剛的App中

library(shiny)

# Define UI for application that plots random distributions 
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("Hello Shiny!"),

  # Sidebar with inputs for number of observations, mean, SD, and coler.
  sidebarPanel(
    sliderInput("obs", "Number of observations:", min = 0, max = 1000, value = 500),
    numericInput("M", "Mean of this normal distribution:", min = -200, max = 200, value = 100),
    numericInput("S", "SD of this normal distribution:", min = 0, max = 50, value = 10),
    radioButtons("Coler", "Select the color of histogram:", choices = c("Red" = "red", "Blue" = "blue", "Green" = "green"))
  ),

  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))
library(shiny)

# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {

    # Expression that generates a plot of the distribution. The expression is
    # wrapped in a call to renderPlot to indicate that:
    # 
    # 1) It is 'reactive' and therefore should be automatically re-executed
    # when inputs change 2) Its output type is a plot
    output$distPlot = renderPlot({

        # generate an rnorm distribution and plot it
        dist = rnorm(input$obs,mean=input$M,sd=input$S)
        hist(dist,col=input$Coler)
    })

})

學習更多R語言的函數

– 一個App要好用,最重要的是它裡面的內容是什麼。

資料來源

下載資料

– 一般來說,即時更新的資料會以網頁方式呈現,而非以Excel相關格式供人下載,因此要擷取即時更新的資料,我們需要讀懂網頁的原始碼。

URL1 = "http://www1.ndmctsgh.edu.tw/ErOnlineNews/ErOnLineData.aspx"

txt1 = scan(URL1, what="character", encoding="UTF-8")

txt1_new = paste(txt1, sep="", collapse=" ")

#The first value
code.1_1 = "<span id=\"Label7\"><font color=\"Red\">"
code.1_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label3\"><font color=\"Blue\">"
start.1 = regexpr(code.1_1, txt1_new)
end.1 = regexpr(code.1_2, txt1_new)
position.1_1 = start.1[1] + attr(start.1,"match.length")
position.1_2 = end.1[1] - 1
value.1=substr(txt1_new, position.1_1, position.1_2)

#The second value
code.2_1 = "<span id=\"Label8\"><font color=\"Red\">"
code.2_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label4\"><font color=\"Blue\">"
start.2 = regexpr(code.2_1, txt1_new)
end.2 = regexpr(code.2_2, txt1_new)
position.2_1 = start.2[1] + attr(start.2,"match.length")
position.2_2 = end.2[1] - 1
value.2=substr(txt1_new, position.2_1, position.2_2)

#The third value
code.3_1 = "<span id=\"Label9\"><font color=\"Red\">"
code.3_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label5\"><font color=\"Blue\">"
start.3 = regexpr(code.3_1, txt1_new)
end.3 = regexpr(code.3_2, txt1_new)
position.3_1 = start.3[1] + attr(start.3,"match.length")
position.3_2 = end.3[1] - 1
value.3=substr(txt1_new, position.3_1, position.3_2)

#The forth value
code.4_1 = "<span id=\"Label10\"><font color=\"Red\">"
code.4_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label6\"><font color=\"Blue\">"
start.4 = regexpr(code.4_1, txt1_new)
end.4 = regexpr(code.4_2, txt1_new)
position.4_1 = start.4[1] + attr(start.4,"match.length")
position.4_2 = end.4[1] - 1
value.4=substr(txt1_new, position.4_1, position.4_2)

#The fifth value
code.5_1 = "<span id=\"Label11\"><font color=\"Red\">"
code.5_2 = "</font></span> </td> </tr> </table> </div> </form> </body> </html>"
start.5 = regexpr(code.5_1, txt1_new)
end.5 = regexpr(code.5_2, txt1_new)
position.5_1 = start.5[1] + attr(start.5,"match.length")
position.5_2 = end.5[1] - 1
value.5=substr(txt1_new, position.5_1, position.5_2)

#look your output
value.1
value.2
value.3
value.4
value.5

自訂函數

TSGH = function() {
URL1 = "http://www1.ndmctsgh.edu.tw/ErOnlineNews/ErOnLineData.aspx"
txt1 = scan(URL1, what="character", encoding="UTF-8")
txt1_new = paste(txt1, sep="", collapse=" ")

#The result matrix
Result=matrix(NA,nrow=1,ncol=5)
rownames(Result)="TSGH"
colnames(Result)=c("Bed status","People waiting for examination","People waiting for bed","People wiating for hospitalize","People waiting for ICU")

#The first value
code.1_1 = "<span id=\"Label7\"><font color=\"Red\">"
code.1_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label3\"><font color=\"Blue\">"
start.1 = regexpr(code.1_1, txt1_new)
end.1 = regexpr(code.1_2, txt1_new)
position.1_1 = start.1[1] + attr(start.1,"match.length")
position.1_2 = end.1[1] - 1
status=substr(txt1_new, position.1_1, position.1_2)
if (status=="是") {Result[1,1]="empty"}
if (status=="否") {Result[1,1]="full"}



#The second value
code.2_1 = "<span id=\"Label8\"><font color=\"Red\">"
code.2_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label4\"><font color=\"Blue\">"
start.2 = regexpr(code.2_1, txt1_new)
end.2 = regexpr(code.2_2, txt1_new)
position.2_1 = start.2[1] + attr(start.2,"match.length")
position.2_2 = end.2[1] - 1
Result[1,2]=substr(txt1_new, position.2_1, position.2_2)

#The third value
code.3_1 = "<span id=\"Label9\"><font color=\"Red\">"
code.3_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label5\"><font color=\"Blue\">"
start.3 = regexpr(code.3_1, txt1_new)
end.3 = regexpr(code.3_2, txt1_new)
position.3_1 = start.3[1] + attr(start.3,"match.length")
position.3_2 = end.3[1] - 1
Result[1,3]=substr(txt1_new, position.3_1, position.3_2)

#The forth value
code.4_1 = "<span id=\"Label10\"><font color=\"Red\">"
code.4_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label6\"><font color=\"Blue\">"
start.4 = regexpr(code.4_1, txt1_new)
end.4 = regexpr(code.4_2, txt1_new)
position.4_1 = start.4[1] + attr(start.4,"match.length")
position.4_2 = end.4[1] - 1
Result[1,4]=substr(txt1_new, position.4_1, position.4_2)

#The fifth value
code.5_1 = "<span id=\"Label11\"><font color=\"Red\">"
code.5_2 = "</font></span> </td> </tr> </table> </div> </form> </body> </html>"
start.5 = regexpr(code.5_1, txt1_new)
end.5 = regexpr(code.5_2, txt1_new)
position.5_1 = start.5[1] + attr(start.5,"match.length")
position.5_2 = end.5[1] - 1
Result[1,5]=substr(txt1_new, position.5_1, position.5_2)

#print the output
return(Result)
}

TSGH()

練習-2

練習-2 答案

TMUSH = function() {
  URL2 = "http://eng.shh.org.tw/ER_WEB/ER_WEB/Default.aspx"
  txt2 = scan(URL2, what="character", encoding="UTF-8")
  txt2_new = paste(txt2, sep="", collapse=" ")
  
  #The result matrix
  Result=matrix(NA,nrow=1,ncol=5)
  rownames(Result)="TMUSH"
  colnames(Result)=c("滿床","看診","推床","住院","加護病床")
  
  #The first value
  code.1_1 = "119滿載</td> <td class=\"style1\"> <span id=\"off\"><b><font color=\"Red\">"
  code.1_2 = "</font></b></span> </td> </tr> <tr> <td class=\"style3\"> 等待看診人數"
  start.1 = regexpr(code.1_1, txt2_new)
  end.1 = regexpr(code.1_2, txt2_new)
  position.1_1 = start.1[1] + attr(start.1,"match.length")
  position.1_2 = end.1[1] - 1
  Result[1,1]=substr(txt2_new, position.1_1, position.1_2)
  
  #The second value
  code.2_1 = "等待看診人數 </td> <td class=\"style1\"> <span id=\"Label1\">"
  code.2_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待推床人數"
  start.2 = regexpr(code.2_1, txt2_new)
  end.2 = regexpr(code.2_2, txt2_new)
  position.2_1 = start.2[1] + attr(start.2,"match.length")
  position.2_2 = end.2[1] - 1
  Result[1,2]=substr(txt2_new, position.2_1, position.2_2)
  
  #The third value
  code.3_1 = "等待推床人數</td> <td> <span id=\"Label2\">"
  code.3_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待住院人數"
  start.3 = regexpr(code.3_1, txt2_new)
  end.3 = regexpr(code.3_2, txt2_new)
  position.3_1 = start.3[1] + attr(start.3,"match.length")
  position.3_2 = end.3[1] - 1
  Result[1,3]=substr(txt2_new, position.3_1, position.3_2)
  
  #The forth value
  code.4_1 = "等待住院人數</td> <td> <span id=\"Label3\">"
  code.4_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待加護人數"
  start.4 = regexpr(code.4_1, txt2_new)
  end.4 = regexpr(code.4_2, txt2_new)
  position.4_1 = start.4[1] + attr(start.4,"match.length")
  position.4_2 = end.4[1] - 1
  Result[1,4]=substr(txt2_new, position.4_1, position.4_2)
  
  #The fifth value
  code.5_1 = "等待加護人數</td> <td> <span id=\"Label4\">"
  code.5_2 = "</span> </td> </tr> </table> <br /> 最後更新"
  start.5 = regexpr(code.5_1, txt2_new)
  end.5 = regexpr(code.5_2, txt2_new)
  position.5_1 = start.5[1] + attr(start.5,"match.length")
  position.5_2 = end.5[1] - 1
  Result[1,5]=substr(txt2_new, position.5_1, position.5_2)
  
  #print the output
  return(Result)
}

TMUSH()

合併兩個函數所產生的結果

Result1=TSGH()
Result2=TMUSH()

Final=rbind(Result1,Result2)
Final

將這個函數寫進你的APP之內

library(shiny)

# Define UI for ER imformation 
shinyUI(pageWithSidebar(
  
  # Application title
  headerPanel("ER imformation"),
  
  # Selected the hospitals
  sidebarPanel(
    radioButtons("language", h3("Selected the language"), c("Chinese" = "1", "English" = "2"))
  ),
  
  # Show a table including user selection
  mainPanel(
    tableOutput("Final")
  )
))
library(shiny)

TSGH = function() {
  URL1 = "http://www1.ndmctsgh.edu.tw/ErOnlineNews/ErOnLineData.aspx"
  txt1 = scan(URL1, what="character", encoding="UTF-8")
  txt1_new = paste(txt1, sep="", collapse=" ")
  
  #The result matrix
  Result=matrix(NA,nrow=1,ncol=5)
  rownames(Result)="TSGH"
  colnames(Result)=c("滿床","看診","推床","住院","加護病床")
  
  #The first value
  code.1_1 = "<span id=\"Label7\"><font color=\"Red\">"
  code.1_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label3\"><font color=\"Blue\">"
  start.1 = regexpr(code.1_1, txt1_new)
  end.1 = regexpr(code.1_2, txt1_new)
  position.1_1 = start.1[1] + attr(start.1,"match.length")
  position.1_2 = end.1[1] - 1
  Result[1,1]=substr(txt1_new, position.1_1, position.1_2)
  
  #The second value
  code.2_1 = "<span id=\"Label8\"><font color=\"Red\">"
  code.2_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label4\"><font color=\"Blue\">"
  start.2 = regexpr(code.2_1, txt1_new)
  end.2 = regexpr(code.2_2, txt1_new)
  position.2_1 = start.2[1] + attr(start.2,"match.length")
  position.2_2 = end.2[1] - 1
  Result[1,2]=substr(txt1_new, position.2_1, position.2_2)
  
  #The third value
  code.3_1 = "<span id=\"Label9\"><font color=\"Red\">"
  code.3_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label5\"><font color=\"Blue\">"
  start.3 = regexpr(code.3_1, txt1_new)
  end.3 = regexpr(code.3_2, txt1_new)
  position.3_1 = start.3[1] + attr(start.3,"match.length")
  position.3_2 = end.3[1] - 1
  Result[1,3]=substr(txt1_new, position.3_1, position.3_2)
  
  #The forth value
  code.4_1 = "<span id=\"Label10\"><font color=\"Red\">"
  code.4_2 = "</font></span> </td> </tr> <tr> <td> <span id=\"Label6\"><font color=\"Blue\">"
  start.4 = regexpr(code.4_1, txt1_new)
  end.4 = regexpr(code.4_2, txt1_new)
  position.4_1 = start.4[1] + attr(start.4,"match.length")
  position.4_2 = end.4[1] - 1
  Result[1,4]=substr(txt1_new, position.4_1, position.4_2)
  
  #The fifth value
  code.5_1 = "<span id=\"Label11\"><font color=\"Red\">"
  code.5_2 = "</font></span> </td> </tr> </table> </div> </form> </body> </html>"
  start.5 = regexpr(code.5_1, txt1_new)
  end.5 = regexpr(code.5_2, txt1_new)
  position.5_1 = start.5[1] + attr(start.5,"match.length")
  position.5_2 = end.5[1] - 1
  Result[1,5]=substr(txt1_new, position.5_1, position.5_2)
  
  #print the output
  return(Result)
}

TMUSH = function() {
  URL2 = "http://eng.shh.org.tw/ER_WEB/ER_WEB/Default.aspx"
  txt2 = scan(URL2, what="character", encoding="UTF-8")
  txt2_new = paste(txt2, sep="", collapse=" ")
  
  #The result matrix
  Result=matrix(NA,nrow=1,ncol=5)
  rownames(Result)="TMUSH"
  colnames(Result)=c("滿床","看診","推床","住院","加護病床")
  
  #The first value
  code.1_1 = "119滿載</td> <td class=\"style1\"> <span id=\"off\"><b><font color=\"Red\">"
  code.1_2 = "</font></b></span> </td> </tr> <tr> <td class=\"style3\"> 等待看診人數"
  start.1 = regexpr(code.1_1, txt2_new)
  end.1 = regexpr(code.1_2, txt2_new)
  position.1_1 = start.1[1] + attr(start.1,"match.length")
  position.1_2 = end.1[1] - 1
  Result[1,1]=substr(txt2_new, position.1_1, position.1_2)
  
  #The second value
  code.2_1 = "等待看診人數 </td> <td class=\"style1\"> <span id=\"Label1\">"
  code.2_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待推床人數"
  start.2 = regexpr(code.2_1, txt2_new)
  end.2 = regexpr(code.2_2, txt2_new)
  position.2_1 = start.2[1] + attr(start.2,"match.length")
  position.2_2 = end.2[1] - 1
  Result[1,2]=substr(txt2_new, position.2_1, position.2_2)
  
  #The third value
  code.3_1 = "等待推床人數</td> <td> <span id=\"Label2\">"
  code.3_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待住院人數"
  start.3 = regexpr(code.3_1, txt2_new)
  end.3 = regexpr(code.3_2, txt2_new)
  position.3_1 = start.3[1] + attr(start.3,"match.length")
  position.3_2 = end.3[1] - 1
  Result[1,3]=substr(txt2_new, position.3_1, position.3_2)
  
  #The forth value
  code.4_1 = "等待住院人數</td> <td> <span id=\"Label3\">"
  code.4_2 = "</span> </td> </tr> <tr> <td class=\"style4\"> 等待加護人數"
  start.4 = regexpr(code.4_1, txt2_new)
  end.4 = regexpr(code.4_2, txt2_new)
  position.4_1 = start.4[1] + attr(start.4,"match.length")
  position.4_2 = end.4[1] - 1
  Result[1,4]=substr(txt2_new, position.4_1, position.4_2)
  
  #The fifth value
  code.5_1 = "等待加護人數</td> <td> <span id=\"Label4\">"
  code.5_2 = "</span> </td> </tr> </table> <br /> 最後更新"
  start.5 = regexpr(code.5_1, txt2_new)
  end.5 = regexpr(code.5_2, txt2_new)
  position.5_1 = start.5[1] + attr(start.5,"match.length")
  position.5_2 = end.5[1] - 1
  Result[1,5]=substr(txt2_new, position.5_1, position.5_2)
  
  #print the output
  return(Result)
}

# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {
  
    output$Final =  renderTable({
      Final=rbind(TSGH(),TMUSH())
      if (input$language=="1") {
        rownames(Final)=c("三軍總醫院","雙和醫院")
        return(Final)
        }
      if (input$language=="2") {return(Final)
        }
    })
  
})

分享你寫的App

  1. 壓縮Myapp資料夾並上傳到GitHub

  2. 自己架設一台伺服器,將檔案放在上面,並請使用者聯結到你的伺服器上使用

  3. 上傳至shinyapps.io

在R之中的準備動作

– 請試著用一開始安裝shiny的方法來安裝devtool

– 複製下面的代碼可以直接下載&安裝完shinyapps (shinyapps套件無法以正常程序安裝)

devtools::install_github('rstudio/shinyapps')
library(shinyapps)

F12

建立R與你的帳戶的聯結

F10

F11

F13

分享

– 點選Publish後,會出現個小視窗,指定檔名後(這也是你未來的網址名稱)就可以上傳至shinyapps.io

F13

小結

  1. 安裝套件
  2. 撰寫App(ui.R以及server.R)
  3. 擷取網頁資訊
  4. 在R內自創函數
  5. 分享你的App