Shiny Basic系列:

参考教程:https://mastering-shiny.org/

(1)IO控件

(2)Layout布局

(3)Reactive用法

(4)Feedback提醒

(5)Module模块

Shiny Package系列:

(1)shinyWidgets

(2)shinyJS

(3)shinydashboard

(4)shinydashboardPlus

(5)bslib

(6)Other pkgs


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Part1 加载shiny包和其他可能需要的包
library(shiny)

# Part2 加载可能需要的数据,函数,模块等

# Part3 设计ui与server
ui <- fluidPage(
  "Hello, world!"
)

server <- function(input, output, session) {
    
}

# Part4 启动app
shinyApp(ui, server)
1
2
3
4
5
6
7
8
# 若检测到相关shiny文件修改,则自动地重新加载;默认为FALSE
options(shiny.autoreload = TRUE)

# 只检测ui.R文件
options(shiny.autoreload.pattern = glob2rx("ui.R"))

# 设置检测周期,默认为500毫秒
options(shiny.autoreload.interval = 2000)

1. 选项选择

1
2
3
4
5
6
7
# Input
selectInput()
selectizeInput()

radioButtons()       #单选
checkboxGroupInput() #多选
checkboxInput()      #逻辑值
  • selectInput()
1
2
3
4
5
6
7
selectInput("id", "label", 
            choices = c("A", "B", "C"),
           	selected = "A",
           	multiple = FALSE)
# choices参数设置选项,可通过named vector友好展示;也可以是list将选项分类
## choices = c("AA"="A", "BB"="B", "CC"="C")
## choices = list('type1' = list("A","B"), 'type2' = list("C","D"))

selectizeInput() 适用于选项过多的情况,用法见第8小点。

  • radioButtons()
1
2
3
4
5
6
7
radioButtons("id", "label",
             choices = c("A", "B", "C"),,
             selected = "A",
             inline = FALSE)
# 类似selectInput,choices参数设置选项,可通过named vector友好展示
## 可通过另外设置参数choiceNames/choiceValues将name(可以是icon等ui元素)与value设置更优雅
# inline 是否将选项在一行内展示
  • checkboxGroupInput()
1
2
3
4
5
# 用法与radioButtons基本类似,主要区别在于可以多选
checkboxGroupInput("id", "label",
                   choices = c("A", "B", "C"),,
                   selected = NULL,
                   inline = FALSE)
  • checkboxInput()
1
2
# 返回逻辑值
checkboxInput("id", "label", value = FALSE)

2. 数值输入

1
2
numericInput()
sliderInput()
  • numericInput()
1
2
3
numericInput("id", "label",
            value = 1, min = 0, max = 10, step = 0.5)
# 只是名义上限制最值,仍然可以手动输入范围以外的值,例如-1
  • sliderInput()
1
2
3
sliderInput("id", "label",
           value = 1, min = 0, max = 10, step = 0.5)
# value可以是长度为2的数值向量,更多参数见帮助文档

3. 文本控件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Input
textInput()
passwordInput() #密码
textAreaInput() #长段

# Output
textOutput()        # plain text
verbatimTextOutput() # code-like text

# renderXXX
renderText() # → textOutput
renderPrint() # → verbatimTextOutput
  • textInput()
1
2
3
textInput("id", "label",
          value = "",
          placeholder = "input some")

4. 表格数据

1
2
3
4
5
6
7
# Output
tableOutput() 
dataTableOutput() 

# renderXXX
renderTable() # → tableOutput
renderDataTable() # → dataTableOutput
  • tableOutput()
1
2
3
4
# 适合小的数据框
tableOutput("id")

renderTable({expr}) #可选参数见帮助文档
  • dataTableOutput()
1
2
3
4
5
6
# 适合大的数据表格
dataTableOutput("id")

renderDataTable({expr},
                options = list()) #可选参数见帮助文档
# https://datatables.net/reference/option/

5. 可视化图

1
2
3
4
5
6
# Output
plotOutput()

# renderXXX
renderPlot() # → plotOutput
renderImage() # → plotOutput
  • plotOutput()
1
2
3
4
5
plotOutput("id", 
          width = "100%", height = "400px")

renderPlot({expr},
          width = "auto", height = "auto", res = 96)

6. 动作按钮

1
2
3
4
actionButton()
actionLink()

actionButton("id", "label", icon = )

icon网站

7. 上传下载

1
2
3
4
5
6
7
8
#上传
fileInput()

#下载
downloadButton()
downloadLink() 

downloadHandler() # server
  • fileInput
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fileInput("id", "label",
         accept = ".csv",
         buttonLabel = "Browse...",
         placeholder = "No file selected")

# accept提醒输入的文件类型(仅为提醒,上传不受限制)
## 可使用validate函数检查 tools::file_ext()获取文件后缀



# 在server端, input$id是一个4列的表格,列名分别是 name, size, type, datapath
## 其中 datapath是读取路径的变量,最有用
## 在初始状态,input为NULL值,可使用req(input$id)防止报错
  • downloadButton
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# ui
downloadButton("id", "label",
              icon = shiny::icon("download"))

# server
output$id <- downloadHandler(
  filename = function() {
    "dataset.csv"
  },
  content = function(file) {
    write.csv(data(), file)
  }
)

8. 动态控件

  • update***:适用于大多数输入控件与动作按钮等UI,用以在server端更新其参数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
updateNumericInput()
updateTextInput()
...

## 简单示例
ui <- fluidPage(
  sliderInput("x1", "x1", 0, min = -10, max = 10),
  actionButton("reset", "Reset")
)

server <- function(input, output, session) {
  observeEvent(input$reset, {
    updateSliderInput(inputId = "x1", value = 0)
  })
}

selectizeInput()适用于动态加载部分选项

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# ui
selectizeInput("id", "label", 
               choices = NULL,
               options = list(create = TRUE,
                              maxOptions = 5,
                              maxItems = 2,
                              placeholder = "select some")
               )
# create 允许新增选项
# maxOptions 界面最多展示5条
# maxItems 多选
               
# server
server <- function(input, output, session) {
  updateSelectizeInput(session, 'id', choices = data, server = TRUE)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# `freezeReactiveValue()`特殊情况(temporary error):
## updateSelectInput() only has an affect after all outputs and observers have run

ui <- fluidPage(
  selectInput("dataset", "Choose a dataset", c("pressure", "cars")),
  selectInput("column", "Choose column", character(0)),
  verbatimTextOutput("summary")
)

server <- function(input, output, session) {
  dataset <- reactive(get(input$dataset, "package:datasets"))
  
  observeEvent(input$dataset, {
    freezeReactiveValue(input, "column") #一般多用于input value
    updateSelectInput(inputId = "column", choices = names(dataset()))
  })
  
  output$summary <- renderPrint({
    summary(dataset()[[input$column]])
  })
}
  • renderUI()/uiOutput()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
ui <- fluidPage(
  textInput("label", "label"),
  selectInput("type", "type", c("slider", "numeric")),
  uiOutput("numeric")
)

server <- function(input, output, session) {
  output$numeric <- renderUI({
    if (input$type == "slider") {
      sliderInput("dynamic", input$label, value = 0, min = 0, max = 10)
    } else {
      numericInput("dynamic", input$label, value = 0, min = 0, max = 10) 
    }
  })
}