R語言程式設計導論

林嶔 (Lin, Chin)

Lesson 13 R網頁App之基本介面函數介紹

第一節:讓你的App可以接受使用者上傳的檔案(1)

– 請在這裡下載練習用檔案

Data=read.table("Example.txt", header = TRUE) #讀取Example.txt,並存成"Data"這個物件(資料表格式)
head(Data, 10) #看"Data"這個資料表的前10個row
##      Height   Weight      BMI Cholesterol Triglyceride
## 1  173.9095 69.30906 22.91623    196.8222     146.4670
## 2  171.1519 66.72796 22.77951    183.2731     152.1301
## 3  169.4500 69.74043 24.28855    193.6936     150.3699
## 4  164.4632 58.76008 21.72426    182.4610     140.6752
## 5  172.2093 64.85015 21.86743    186.5315     146.7873
## 6  166.4883 66.17726 23.87489    187.4913     165.1633
## 7  177.2201 92.62094 29.49057    211.4545     167.2411
## 8  177.6544 85.45003 27.07448    203.5222     166.3448
## 9  175.4248 89.43701 29.06267    208.3781     164.0171
## 10 163.2245 55.52598 20.84133    185.0684     149.5531
summary(Data) #看"Data"這個資料表的所有變項的基本資訊
##      Height          Weight            BMI         Cholesterol   
##  Min.   :143.6   Min.   : 35.15   Min.   :13.66   Min.   :161.7  
##  1st Qu.:162.9   1st Qu.: 63.47   1st Qu.:22.54   1st Qu.:187.2  
##  Median :170.6   Median : 69.75   Median :24.62   Median :197.6  
##  Mean   :168.7   Mean   : 70.83   Mean   :24.75   Mean   :196.2  
##  3rd Qu.:173.7   3rd Qu.: 80.53   3rd Qu.:27.21   3rd Qu.:204.8  
##  Max.   :197.5   Max.   :103.20   Max.   :35.32   Max.   :219.6  
##   Triglyceride  
##  Min.   :114.0  
##  1st Qu.:149.7  
##  Median :158.6  
##  Mean   :158.6  
##  3rd Qu.:167.0  
##  Max.   :194.9

第一節:讓你的App可以接受使用者上傳的檔案(2)

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Summarize your data"), 
  
  sidebarPanel(
    fileInput(inputId="files", label=h4("Upload your data file:"), multiple=FALSE, accept="text/plain"),
    helpText("Note: you only can upload the .txt file."),
    sliderInput("n", h4("Select the observed rows:"), min=5, max=20, value=10)
  ),
    
  mainPanel(
    verbatimTextOutput("summary"),  
    tableOutput("view")  
  )  
  
))
library(shiny)

shinyServer(function(input, output) {
    
  output$summary = renderPrint({
    if (is.null(input$files)==TRUE) {return("You have to up load your data!!!")} else {
      dat = read.table(input$files$datapath, header = TRUE)
      summary(dat)                     
    }        
  })
  
  output$view = renderTable({
    if (is.null(input$files)==TRUE) {return()} else {
      dat = read.table(input$files$datapath, header = TRUE)
      head(dat, input$n)                     
    }        
  })
  
})

練習1:為你的App增加一張圖

– radioButtons() in ui.R(單選題)

– plotOutput() in ui.R(輸出圖形)

– renderPlot() in server.R(處理圖形)

Data = read.table("Example.txt",header=TRUE) #讀取Example.txt,並存成"Data"這個物件(資料表格式)
head(Data, 10) #看"Data"這個資料表的前10個row
##      Height   Weight      BMI Cholesterol Triglyceride
## 1  173.9095 69.30906 22.91623    196.8222     146.4670
## 2  171.1519 66.72796 22.77951    183.2731     152.1301
## 3  169.4500 69.74043 24.28855    193.6936     150.3699
## 4  164.4632 58.76008 21.72426    182.4610     140.6752
## 5  172.2093 64.85015 21.86743    186.5315     146.7873
## 6  166.4883 66.17726 23.87489    187.4913     165.1633
## 7  177.2201 92.62094 29.49057    211.4545     167.2411
## 8  177.6544 85.45003 27.07448    203.5222     166.3448
## 9  175.4248 89.43701 29.06267    208.3781     164.0171
## 10 163.2245 55.52598 20.84133    185.0684     149.5531
summary(Data) #看"Data"這個資料表的所有變項的基本資訊
##      Height          Weight            BMI         Cholesterol   
##  Min.   :143.6   Min.   : 35.15   Min.   :13.66   Min.   :161.7  
##  1st Qu.:162.9   1st Qu.: 63.47   1st Qu.:22.54   1st Qu.:187.2  
##  Median :170.6   Median : 69.75   Median :24.62   Median :197.6  
##  Mean   :168.7   Mean   : 70.83   Mean   :24.75   Mean   :196.2  
##  3rd Qu.:173.7   3rd Qu.: 80.53   3rd Qu.:27.21   3rd Qu.:204.8  
##  Max.   :197.5   Max.   :103.20   Max.   :35.32   Max.   :219.6  
##   Triglyceride  
##  Min.   :114.0  
##  1st Qu.:149.7  
##  Median :158.6  
##  Mean   :158.6  
##  3rd Qu.:167.0  
##  Max.   :194.9
Color = "red"
plot(Data, col = Color)

練習-1 答案

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Summarize your data"), 
  
  sidebarPanel(
    fileInput(inputId="files", label=h4("Upload your data file:"), multiple=FALSE, accept="text/plain"),
    helpText("Note: you only can upload the .txt file."),
    sliderInput("n", h4("Select the observed rows:"), min=5, max=20, value=10),
    radioButtons("Color", "Select the color of histogram:", choices = c("Red" = "red", "Blue" = "blue", "Green" = "green"))
  ),
    
  mainPanel(
    verbatimTextOutput("summary"),
    plotOutput("scatterPlot"),
    tableOutput("view")  
  )  
  
))
library(shiny)

shinyServer(function(input, output) {
    
  DATA = reactive({
    if (is.null(input$files)) {return()} else {
      dat = read.table(input$files$datapath,header=T)
      return(dat) 
    }
  })
  
  output$summary = renderPrint({
    dat = DATA()
    if (is.null(dat)) {return("You have to up load your data!!!")} else {
      summary(dat)
    }
  })
  
  output$scatterPlot = renderPlot({
    dat = DATA()
    if (is.null(dat)) {return()} else {
      plot(dat,col=input$Color)
    }
  })
  
  output$view = renderTable({
    dat = DATA()
    if (is.null(dat)) {return()} else {
      head(dat,input$n) 
    }
  })

})

第二節:完整的學習控制區的互動參數(1)

##               Functions            Inputs
## 1  checkboxGroupInput()   selected values
## 2       checkboxInput()           logical
## 3           dateInput()              date
## 4      dateRangeInput()           2 dates
## 5           fileInput()         file name
## 6        numericInput()           numeric
## 7        radioButtons()    selected value
## 8         selectInput() selected value(s)
## 9         sliderInput()           numeric
## 10       submitButton()           numeric
## 11          textInput()         character

– 請在這裡下載基本物件範例

練習2:熟練地使用互動物件

– 請在這裡下載練習用檔案

  1. 可以允許使用者上傳範例檔案
  2. 在按下按鈕後可以畫出散布圖
  3. 讓使用者選擇散布圖的顏色
  4. 讓使用者能下載這張散布圖
  5. 有餘力的話,發揮你的創意增加控制bar
Data = read.table("Example.txt", header = TRUE) #讀取Example.txt,並存成"Data"這個物件(資料表格式)

Color = "red"          #指定顏色

pdf("plot.pdf")      #開啟一個pdf file,路徑為"plot.pdf"
plot(Data, col = Color) #將圖畫到開啟中的pdf file上去
dev.off()            #關掉這個pdf file

練習2答案

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Ploting your data"), 
  
  sidebarPanel(
    fileInput(inputId="files", label=h4("Upload your data file:"), multiple=FALSE, accept="text/plain"),
    helpText("Note: you only can upload the .txt file."),
    radioButtons("Color", "Select the color of histogram:", choices = c("Red" = "red", "Blue" = "blue", "Green" = "green"))
  ),
    
  mainPanel(
    plotOutput("scatterPlot"),
    downloadButton("download", label = "Download plot", class = NULL)
  )  
  
))
library(shiny)

shinyServer(function(input, output) {
    
  DATA = reactive({
    if (is.null(input$files)) {return()} else {
      dat = read.table(input$files$datapath,header=T)
      return(dat) 
    }
  })
  
  output$scatterPlot = renderPlot({
    dat = DATA()
    if (is.null(dat)) {return()} else {
      plot(dat,col=input$Color)
    }
  })
  
  output$download = downloadHandler(
    filename = function() {'plot.pdf'},
    content = function(con) {
      dat = DATA()
      if (is.null(dat)) {return()} else {
        pdf(con)
        plot(dat,col=input$Color)
        dev.off()
      }
    }
  )

})

第三節:使控制區的參數隨著Server端的狀況而改變(1)

– 所以,如果可以的話,我們希望左側的控制區可以出現一個選單,列出使用者所上傳的檔案的所有的變項名稱,並且讓使用者能選擇他想要分析的變項。

Data = read.table("Example.txt", header = TRUE)
head(Data, 10)
##      Height   Weight      BMI Cholesterol Triglyceride
## 1  173.9095 69.30906 22.91623    196.8222     146.4670
## 2  171.1519 66.72796 22.77951    183.2731     152.1301
## 3  169.4500 69.74043 24.28855    193.6936     150.3699
## 4  164.4632 58.76008 21.72426    182.4610     140.6752
## 5  172.2093 64.85015 21.86743    186.5315     146.7873
## 6  166.4883 66.17726 23.87489    187.4913     165.1633
## 7  177.2201 92.62094 29.49057    211.4545     167.2411
## 8  177.6544 85.45003 27.07448    203.5222     166.3448
## 9  175.4248 89.43701 29.06267    208.3781     164.0171
## 10 163.2245 55.52598 20.84133    185.0684     149.5531
summary(Data) 
##      Height          Weight            BMI         Cholesterol   
##  Min.   :143.6   Min.   : 35.15   Min.   :13.66   Min.   :161.7  
##  1st Qu.:162.9   1st Qu.: 63.47   1st Qu.:22.54   1st Qu.:187.2  
##  Median :170.6   Median : 69.75   Median :24.62   Median :197.6  
##  Mean   :168.7   Mean   : 70.83   Mean   :24.75   Mean   :196.2  
##  3rd Qu.:173.7   3rd Qu.: 80.53   3rd Qu.:27.21   3rd Qu.:204.8  
##  Max.   :197.5   Max.   :103.20   Max.   :35.32   Max.   :219.6  
##   Triglyceride  
##  Min.   :114.0  
##  1st Qu.:149.7  
##  Median :158.6  
##  Mean   :158.6  
##  3rd Qu.:167.0  
##  Max.   :194.9

– 還記得如何做linear regression吧?

Result = lm(Weight~Height, data = Data) #linear regression test
Result
## 
## Call:
## lm(formula = Weight ~ Height, data = Data)
## 
## Coefficients:
## (Intercept)       Height  
##    -79.4208       0.8904
summary(Result)
## 
## Call:
## lm(formula = Weight ~ Height, data = Data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -28.2430  -6.6118  -0.7133   6.7464  25.6051 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -79.42076   15.28220  -5.197 1.11e-06 ***
## Height        0.89043    0.09039   9.851 2.55e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 9.552 on 98 degrees of freedom
## Multiple R-squared:  0.4975, Adjusted R-squared:  0.4924 
## F-statistic: 97.04 on 1 and 98 DF,  p-value: 2.552e-16

– 畫張散佈圖吧!

plot(Data$Height, Data$Weight, pch = 19)
abline(Result)

第三節:使控制區的參數隨著Server端的狀況而改變(2)

Data=read.table("Example.txt", header = TRUE)
colnames(Data)    # 列出所有的欄位名稱
## [1] "Height"       "Weight"       "BMI"          "Cholesterol"  "Triglyceride"
colnames(Data)[1] # 列出第一個欄位名稱
## [1] "Height"
colnames(Data)[4] # 列出第四個欄位名稱(依此類推)
## [1] "Cholesterol"
Result1 = lm(Data[,"Weight"]~Data[,"Height"])
summary(Result1)
## 
## Call:
## lm(formula = Data[, "Weight"] ~ Data[, "Height"])
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -28.2430  -6.6118  -0.7133   6.7464  25.6051 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      -79.42076   15.28220  -5.197 1.11e-06 ***
## Data[, "Height"]   0.89043    0.09039   9.851 2.55e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 9.552 on 98 degrees of freedom
## Multiple R-squared:  0.4975, Adjusted R-squared:  0.4924 
## F-statistic: 97.04 on 1 and 98 DF,  p-value: 2.552e-16

第三節:使控制區的參數隨著Server端的狀況而改變(3)

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Linear regression for two continuous variables."), 
  
  sidebarPanel(
    fileInput(inputId="files", label=h4("Upload your data file:"), multiple=FALSE, accept="text/plain"),
    helpText("Note: you only can upload the .txt file."),
    uiOutput("choose_columns1"),   #這裡是關鍵
    uiOutput("choose_columns2")    #這裡是關鍵
  ),
  
  mainPanel(
    verbatimTextOutput("summary"),
    plotOutput("plot",width = "500px", height = "500px")
  )  
  
))
library(shiny)

shinyServer(function(input, output) {
  
  DATA <- reactive({
    if (is.null(input$files)) {return()} else {
      dat <- read.table(input$files$datapath,header=T)
      return(dat) 
    }
  })
  
  output$choose_columns1 <- renderUI({  #這裡是關鍵
    dat = DATA()
    if (is.null(dat)) {return()} else {
      colnames <- colnames(dat)
      selectInput("Y", h4("Choose a dependence variable:"), choices = colnames)
    }
  })
  
  output$choose_columns2 <- renderUI({  #這裡是關鍵
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)) {return()} else {
      colnames <- colnames(dat)
      selectInput("X", h4("Choose a independence variable:"), choices = colnames[which(colnames!=input$Y)])
    }
  })
  
  output$summary <- renderPrint({
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)|is.null(input$X)) {return()} else {
      X <- dat[,input$X]  #這裡是關鍵
      Y <- dat[,input$Y]  #這裡是關鍵
      Result=lm(Y~X)
      return(summary(Result))
    }  
  })
  
  output$plot <- renderPlot({
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)|is.null(input$X)) {return()} else {
      X <- dat[,input$X]  #這裡是關鍵
      Y <- dat[,input$Y]  #這裡是關鍵
      plot(X,Y,pch=19)
      abline(lm(Y~X),col="black")   
    }  
  })
  
})

練習3:換個分析方法

Result1 = cor.test(Data[,"Weight"], Data[,"Height"], method = "pearson") # Pearson correlation
Result1
## 
##  Pearson's product-moment correlation
## 
## data:  Data[, "Weight"] and Data[, "Height"]
## t = 9.8507, df = 98, p-value = 2.552e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.5907925 0.7920433
## sample estimates:
##       cor 
## 0.7053591
Result2 = cor.test(Data[,"Weight"], Data[,"Height"], method = "spearman") # Spearman correlation
Result2
## 
##  Spearman's rank correlation rho
## 
## data:  Data[, "Weight"] and Data[, "Height"]
## S = 49490, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##       rho 
## 0.7030303

– 請依照剛剛的範例,設計一個選單,讓使用者能指定要使用Pearson correlation還是Spearman correlation。

– 當然,能讓使用者改個散布圖的顏色也是必須的…

練習3答案

library(shiny)

shinyUI(pageWithSidebar(
  
  headerPanel("Linear regression for two continuous variables."), 
  
  sidebarPanel(
    fileInput(inputId="files", label=h4("Upload your data file:"), multiple=FALSE, accept="text/plain"),
    helpText("Note: you only can upload the .txt file."),
    uiOutput("choose_columns1"),   #這裡是關鍵
    uiOutput("choose_columns2"),   #這裡是關鍵
    radioButtons("method", "What is the method to analysis?", choices = c("Pearson correlation" = "pearson", "Spearman correlation" = "spearman")),
    radioButtons("Color", "Select the color of histogram:", choices = c("Red" = "red", "Blue" = "blue", "Green" = "green"))
  ),
  
  mainPanel(
    verbatimTextOutput("summary"),
    plotOutput("plot",width = "500px", height = "500px")
  )  
  
))
library(shiny)

shinyServer(function(input, output) {
  
  DATA <- reactive({
    if (is.null(input$files)) {return()} else {
      dat <- read.table(input$files$datapath,header=T)
      return(dat) 
    }
  })
  
  output$choose_columns1 <- renderUI({  #這裡是關鍵
    dat = DATA()
    if (is.null(dat)) {return()} else {
      colnames <- colnames(dat)
      selectInput("Y", h4("Choose a dependence variable:"), choices = colnames)
    }
  })
  
  output$choose_columns2 <- renderUI({  #這裡是關鍵
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)) {return()} else {
      colnames <- colnames(dat)
      selectInput("X", h4("Choose a independence variable:"), choices = colnames[which(colnames!=input$Y)])
    }
  })
  
  output$summary <- renderPrint({
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)|is.null(input$X)) {return()} else {
      X <- dat[,input$X]  #這裡是關鍵
      Y <- dat[,input$Y]  #這裡是關鍵
      Result=cor.test(X,Y,method=input$method)
      return(Result)
    }  
  })
  
  output$plot <- renderPlot({
    dat = DATA()
    if (is.null(dat)|is.null(input$Y)|is.null(input$X)) {return()} else {
      X <- dat[,input$X]  #這裡是關鍵
      Y <- dat[,input$Y]  #這裡是關鍵
      plot(X,Y,pch=19,col=input$Color)
      abline(lm(Y~X),col="black")   
    }  
  })
  
})

小結

  1. 控制區的基本互動參數應已熟悉
  2. 更熟悉上傳/下載檔案的功能
  3. renderUI及uiOutput
  4. 認識了更多UI模組
  5. 了解如何做UI的優化