Chin Lin
Thursday, September 25, 2014
許多時候我們希望可以將我們的工作成果與其他人分享,同時也希望別人可以簡單的享用這些資源,這時候WebApp就是一個很好的媒介。
WebApp有下列優點:
只需要連上網路即可使用
透過互動清楚的展示你所想表達的事物
對於使用者來說非常簡單上手
R語言可能是所有程式語言中最容易上手的,並且它支援非常多統計方法的使用,除此之外,他還是個免費的資源。
要開始使用R,你必須先到http://www.r-project.org/下載檔案,安裝後才可以使用
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")
)
))
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)
})
})
前面已經說過,使用shiny(R package)所撰寫的App,他的基本構造是一個包含ui.R(主管使用者介面)以及server.R(主管伺服器端的處理)的資料夾。
Shiny app的基本運作流程為:
使用者自ui.R中的給定一個參數。
這個參數傳到server.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")
)
))
headerPanel()用來定義網頁標題
sidebarPanel()用來定義的控制選單內含哪些可控參數,本例中只有一個滑動輸入元件sliderInput(),元件為obs
mainPanle()則是用來定義輸出區域的輸出結果,本例中只有一個圖片輸出元件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)
hist(dist)
})
})
其中是以shinyServer()這個函數為開頭,裡面包含著一個函數function()要求你指定input及output,由於我們只要做一個反應函數,由於我們想要畫一張圖,所以使用renderPlot()函數,在裡面我們指定它畫圖的過程,並且將結果儲存在output裡面的distPlot。
這個畫圖的過程很簡單,就是先指定一個數字(由input$obs提供,也就是剛剛在ui.R中使用者所給定的參數),然後要求R使用rnorm()隨機產生n個平均數為0,標準差為1的數列,而這個數列儲存在dist元件內。接著在以hist(dist)畫出這個數列的直方圖。
因此,在renderPlot()函數內,我們根據使用者指定的參數(input$obs)產生了一張直方圖,而這張直方圖將會儲存在output裡面的distPlot。
接著這個物件distPlot就會回到ui.R中,而根據我們在ui.R中所下的指令,他將會使用plotOutput()函數使這張圖形呈現在輸出區上。
Note:所有的輸入元件都存取在input這個List內;而所有的輸出元件都存取在output這個List內。
至此為止,我們已經學會了webApp的基本寫法。然而這時候若需要進一步的增加它的應用面,我們需要的是學習更多R裡面的函數,讓我們的App可以擁有更強大的功能。
請在R內練習下列這段程式碼的使用,並試圖改變裡面的obs,M,S,Coler的數字,了解他的功能
obs = 500
M = 170
S = 10
Coler = "blue"
dist = rnorm(obs,mean=M,sd=S)
hist(dist,col=Coler)
在剛剛的練習中我們已經清楚了在R裡面,改變參數可以改變圖形的常態分布,接著我們可以開始增加這些參數至我們剛剛寫的App內。
除了已經存在的obs之外,我們將繼續增加M,S,Coler在我們的控制區域之內。
ui.R
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)
})
})
– 一個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()
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
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")
)
))
在伺服器端,我們需要在最上面自訂我們所寫的函數,這樣伺服器端才能使用這兩個函數
server.R
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)
}
})
})
壓縮Myapp資料夾並上傳到GitHub
自己架設一台伺服器,將檔案放在上面,並請使用者聯結到你的伺服器上使用
上傳至shinyapps.io
– 請試著用一開始安裝shiny的方法來安裝devtool
– 複製下面的代碼可以直接下載&安裝完shinyapps (shinyapps套件無法以正常程序安裝)
devtools::install_github('rstudio/shinyapps')
library(shinyapps)
上面那些動作完成之後,接著你已經可以用非常簡單的方式來分享你寫好的App了。
請你回到ui.R或server.R的編輯視窗內,並且先按RunApp,然後我們會看到左上角有一個Publish的按鍵。
– 點選Publish後,會出現個小視窗,指定檔名後(這也是你未來的網址名稱)就可以上傳至shinyapps.io了