Shiny从入门到入定——2-在大大的花园里面挖呀挖呀挖
发表于:2023-11-18 | 分类: IT
字数统计: 3.6k | 阅读时长: 14分钟 | 阅读量:

基础 UI

引言

现在,您已经具备了基本的 Shiny 应用程序,我们可以开始详细探索使 Shiny 起作用的内容。正如您在上一章所看到的,Shiny 鼓励将生成用户界面(前端)的代码与驱动应用程序行为的代码(后端)分开。

在本章中,我们将重点关注前端,并向您展示由 Shiny 提供的 HTML 输入和输出的大致情况。这使您能够捕获许多类型的表单数据,并显示许多类型的 R 输出。到目前为止,您可能还没有很多将输入和输出拼接在一起的方法,我们将在第 6 章中回顾这一点。

在这里,我将主要关注 Shiny 自身内置的输入和输出。但是,还有一个丰富而充满活力的社区扩展包,例如 shinyWidgetscolorpicker sorttable。您可以在 https://github.com/nanxstats/awesome-shiny-extensions 找到其他全面且维护良好的包列表,该列表由 Nan Xiao 维护。

与往常一样,我们将从加载 shiny 包开始:

library(shiny)

输入

正如我们在上一章所看到的,您使用诸如 sliderInput()selectInput()textInput()numericInput() 之类的函数将输入控件插入到您的 UI 规范中。现在我们将讨论所有输入函数所共有的常见结构,并为内置在 Shiny 中的输入提供快速概述。

常见结构

所有输入函数都具有相同的第一个参数: inputId 。这是用于将前端与后端连接的标识符:如果您的用户界面具有 ID 为 name 的输入,则 server 函数将使用 input$name 来访问它。

inputId 有两个约束:

  • 它必须是一个简单的字符串,只包含字母、数字和下划线(不允许空格、破折号、句点或其他特殊字符!)以 R 命名变量。

  • 它必须是唯一的。如果它不是唯一的,那么您将无法在 server 函数中引用此控件!

大多数输入函数都有一个称为 label 的第二个参数。这是用于为控件创建一个人类可读的标签。Shiny 对此字符串没有任何限制,但您需要仔细考虑,以确保您的应用程序对人类可用!第三个参数通常是 value ,在可能的情况下,允许您设置默认值。其余参数是控件特有的。

创建输入时,我建议按位置提供 inputId 和 label 参数,并按名称提供所有其他参数:

sliderInput("min", "Limit (minimum)", value = 50, min = 0, max = 100)

以下部分描述了 Shiny 内置的输入,根据它们创建的控制类型松散分组。目标是让您快速了解您的选项,而不是详尽地描述所有参数。下面我将展示每个控件最重要的参数,但您需要阅读文档以获得完整详细信息。

自由文本

使用 textInput() 收集少量文本,使用 passwordInput() 3收集密码,使用 textAreaInput() 收集段落文本。

ui <- fluidPage(
  textInput("name", "What's your name?"),
  passwordInput("password", "What's your password?"),
  textAreaInput("story", "Tell me about yourself", rows = 3)
)

text

如果你想确保文本具有某些属性,你可以使用 validate() ,我们将在第 8 章中介绍这个函数。

数值输入

要收集数值,请使用 numericInput() 创建一个受约束的文本框,或使用 sliderInput() 创建一个滑块。如果你为 sliderInput () 的默认值提供一个长度为 2 的数值向量,你将获得一个带有两个端点的 “范围” 滑块。

ui <- fluidPage(
  numericInput("num", "Number one", value = 0, min = 0, max = 100),
  sliderInput("num2", "Number two", value = 50, min = 0, max = 100),
  sliderInput("rng", "Range", value = c(10, 20), min = 0, max = 100)
)

numeric

一般来说,我只建议在范围较小或者精确数值不太重要的情况下使用滑块。尝试在小的滑块上精确选择一个数字是一件很令人沮丧的事情!

滑块非常可定制,有很多方法可以调整它们的外观。更多细节请参见 ?sliderInput https://shiny.rstudio.com/articles/sliders.html

日期

使用 dateInput() 收集单个日期,或使用 dateRangeInput() 收集两个日期之间的范围。这些都提供了一个方便的日历选择器,额外的参数如 datesdisableddaysofweekdisabled 允许您限制有效的输入集。

ui <- fluidPage(
  dateInput("dob", "When were you born?"),
  dateRangeInput("holiday", "When do you want to go on vacation next?")
)

date

日期格式、语言和一周开始的日期默认采用美国标准。如果您正在为国际用户创建应用程序,请设置格式、语言和一周开始日期,以便日期对您的用户来说是自然的。

有限制的选择

有两种不同的方法允许用户从预设的选项集中进行选择: selectInput()radioButtons()

animals <- c("dog", "cat", "mouse", "bird", "other", "I hate animals")

ui <- fluidPage(
  selectInput("state", "What's your favourite state?", state.name),
  radioButtons("animal", "What's your favourite animal?", animals)
)

choice

单选按钮有两个很好的特点:它们显示所有可能的选项,适合于短列表,并且通过 choiceNames/choiceValues 参数,它们可以显示除普通文本之外的其他选项。 choiceNames 确定向用户显示的内容; choiceValues 确定在您的 server 函数中返回的内容。

ui <- fluidPage(
  radioButtons("rb", "Choose one:",
    choiceNames = list(
      icon("angry"),
      icon("smile"),
      icon("sad-tear")
    ),
    choiceValues = list("angry", "happy", "sad")
  )
)
#> This Font Awesome icon ('angry') does not exist:
#> * if providing a custom `html_dependency` these `name` checks can 
#>   be deactivated with `verify_fa = FALSE`
#> This Font Awesome icon ('smile') does not exist:
#> * if providing a custom `html_dependency` these `name` checks can 
#>   be deactivated with `verify_fa = FALSE`
#> This Font Awesome icon ('sad-tear') does not exist:
#> * if providing a custom `html_dependency` these `name` checks can 
#>   be deactivated with `verify_fa = FALSE`

单选按钮

使用 selectInput() 创建的下拉菜单无论选项数量多少,都占用相同数量的空间,这使得它们更适合于更长的选项。您还可以设置 multiple = TRUE 以允许用户选择多个元素。

ui <- fluidPage(
  selectInput(
    "state", "What's your favourite state?", state.name,
    multiple = TRUE
  )
)

下拉菜单

如果你有一组非常大的可能选项,你可能想要使用 “server-side” selectInput() ,这样完整的可能选项集不被嵌入到 UI 中(这可能会使加载变慢),而是由服务器按需发送。您可以了解有关此高级主题的更多信息,请访问 https://shiny.rstudio.com/articles/selectize.html#server-side-selectize

没有方法可以在单选按钮中选择多个值,但有一个概念上类似的替代方案: checkboxGroupInput()

ui <- fluidPage(
  checkboxGroupInput("animal", "What animals do you like?", animals)
)

如果您想要一个单选框来回答一个 Yes/No 问题,请使用 checkboxInput()

ui <- fluidPage(
  checkboxInput("cleanup", "Clean up?", value = TRUE),
  checkboxInput("shutdown", "Shutdown?")
)

文件上传

允许用户通过 fileInput() 上传文件:

ui <- fluidPage(
  fileInput("upload", NULL)
)

上传文件

fileInput () 需要在 server 端进行特殊处理,并在第 9 章中详细讨论。

动作按钮

使用 actionButton()actionLink() 让用户执行动作。

ui <- fluidPage(
  actionButton("click", "Click me!"),
  actionButton("drink", "Drink me!", icon = icon("cocktail"))
)
#> This Font Awesome icon ('cocktail') does not exist:
#> * if providing a custom `html_dependency` these `name` checks can 
#>   be deactivated with `verify_fa = FALSE`

按钮

动作链接和按钮最自然地与 server 函数中的 observeEvent()eventReactive() 配对。您还没有学习这些重要的函数,但我们在第 3.5 节中会回到它们。

您可以使用 class 参数来自定义外观,使用 "btn-primary""btn-success""btn-info""btn-warning""btn-danger" 之一。您还可以使用 "btn-lg""btn-sm""btn-xs" 更改大小。最后,您可以使用 "btn-block" 使按钮跨越其嵌入的元素的整个宽度。

ui <- fluidPage(
  fluidRow(
    actionButton("click", "Click me!", class = "btn-danger"),
    actionButton("drink", "Drink me!", class = "btn-lg btn-success")
  ),
  fluidRow(
    actionButton("eat", "Eat me!", class = "btn-block")
  )
)

class 参数通过设置底层 HTML 的 class 属性来工作,这会影响元素的样式。要查看其他选项,您可以阅读 Shiny 使用的 CSS 设计系统 Bootstrap 的文档:http://bootstrapdocs.com/v3.3.6/docs/css/#buttons

练习

2.2.8.1 当空间不足时,使用一个出现在文本输入区域内的占位符来标记文本框很有用。您如何调用 textInput() 生成下面的 UI?

2.2.8.1

2.2.8.2 认真阅读 sliderInput() 的文档以了解如何创建日期滑块,如下:

日历滑块

2.2.8.3 如何创建日期滑块,使得用户可以在 0 到 100 之间选择日期,滑块上每个可选值的间隔为 5。然后,为输入小部件添加动画,以便当用户按下播放时,输入小部件会自动滚动到该范围。

2.2.8.4 如果您有一个中等长度的 selectInput() 列表,创建子标签是有用的,它可以将列表分成几部分。阅读文档以了解如何操作。(提示:底层 HTML 称为 <optgroup> 。)

输出

用户界面中的输出创建了占位符,稍后将由 server 函数填充。与输入一样,输出需要一个唯一的 ID 作为其第一个参数:如果您的用户界面规范创建了一个 ID 为 plot 的输出,您可以通过 output$plot 在服务器函数中访问它。

前端中的每个输出函数都与后端的渲染函数配对。有三种主要的输出类型,对应于您通常在报告中包含的三件事: 文本表格图形 。以下部分向您展示了前端输出函数的基本知识,以及后端相应的渲染函数。

文本

使用 textOutput() 输出普通文本,使用 verbatimTextOutput() 输出固定代码和控制台输出。

ui <- fluidPage(
  textOutput("text"),
  verbatimTextOutput("code")
)
server <- function(input, output, session) {
  output$text <- renderText({ 
    "Hello friend!" 
  })
  output$code <- renderPrint({ 
    summary(1:10) 
  })
}

请注意,只有在需要运行多行代码时, {} 才需要在渲染函数中使用。正如您即将了解的那样,您应该在渲染函数中尽可能少地进行计算,这意味着您通常可以省略它们。以下是上述 server 函数更简洁的方式:

server <- function(input, output, session) {
  output$text <- renderText("Hello friend!")
  output$code <- renderPrint(summary(1:10))
}

注意,有两种渲染函数的行为略有不同:

  • renderText() 将结果合并成一个字符串,通常与 textOutput() 配对

  • renderPrint() 打印结果,就像在 R 控制台中一样,通常与 verbatimTextOutput() 配对。

我们可以通过一个玩具应用程序看到这种差异:

ui <- fluidPage(
  textOutput("text"),
  verbatimTextOutput("print")
)
server <- function(input, output, session) {
  output$text <- renderText("hello!")
  output$print <- renderPrint("hello!")
}

二者的区别与 R 中的 cat() and print() 一样。

表格

有三种方法可以在表格中显示数据框:

  • tableOutput()renderTable() 呈现静态数据表,一次显示所有数据。

  • dataTableOutput()renderDataTable() 呈现动态数据表,一次显示固定数量的行,同时显示控件以更改可见行。

tableOutput() 最适合小型、固定的摘要(例如模型系数);如果您想向用户展示完整的数据框, dataTableOutput() 最为合适。如果您想更精确地控制 dataTableOutput() 的输出,我强烈推荐 Greg Lin 的 reactable 包。

ui <- fluidPage(
  tableOutput("static"),
  dataTableOutput("dynamic")
)
server <- function(input, output, session) {
  output$static <- renderTable(head(mtcars))
  output$dynamic <- renderDataTable(mtcars, options = list(pageLength = 5))
}

表格

图形

您可以使用 plotOutput()renderPlot() 显示任何类型的 R 图形(基础、ggplot2 或其他)。

ui <- fluidPage(
  plotOutput("plot", width = "400px")
)
server <- function(input, output, session) {
  output$plot <- renderPlot(plot(1:5), res = 96)
}

绘图

默认情况下, plotOutput() 将占据其容器的全部宽度(稍后将详细介绍),高度为 400 像素。您可以使用 heightwidth 参数覆盖这些默认值。我们建议始终将 res 设置为 96,这样您的 Shiny 图形就会尽可能与 RStudio 中看到的图形相匹配。

图形是特殊的输出,因为它们也可以作为输入。 plotOutput() 具有许多参数,如 clickdblclickhover 。如果您将这些参数传递给字符串,例如 click = "plot_click" ,则它们将创建一个可响应的输入( input$plot_click ),您可以使用它来处理与图形的用户交互,例如单击图形。我们将在第 7 章中再次讨论 Shiny 中的交互式图形。

下载

您可以使用 downloadButton()downloadLink() 让用户下载文件。这些需要在 server 函数中使用新技术,因此我们将在第 9 章中详细介绍。

练习

2.3.5.1 下列哪个应与 textOutput()verbatimTextOutput() 配对?

a. renderPrint(summary(mtcars))

b. renderText("Good morning!")

c. renderPrint(t.test(1:5, 2:6))

d. renderText(str(lm(mpg ~ wt, data = mtcars)))

2.3.5.2 重新创建第 2.3.3 节的 Shiny 应用程序,这次将高度设置为 300 像素,宽度设置为 700 像素。设置图的 “alt” 文本,以便视障用户可以判断其是五个随机数的散点图。

2.3.5.3 更新以下调用 renderDataTable() 的选项,以便仅显示数据,但其他控件均被抑制(即删除搜索、排序和过滤命令)。您需要阅读?renderDataTable 并回顾 https://datatables.net/reference/option/ 中的选项。

ui <- fluidPage(
  dataTableOutput("table")
)
server <- function(input, output, session) {
  output$table <- renderDataTable(mtcars, options = list(pageLength = 5))
}

2.3.5.4 或者,您可以阅读 reactable 的文档,并将上面的应用程序转换为使用它。

总结

本章向您介绍了 Shiny 应用程序前端的主要输入和输出功能。这是一次大量的信息灌输,因此不要期望在一次阅读后就能记住所有内容。相反,当您需要查找特定组件时,请返回本章:您可以快速浏览图示,然后找到您需要的代码。

下一章我们将介绍 Shiny 应用程序的后端:使您的用户界面生动起来的 R 代码。

练习题答案获取

关注公众号 “生信之巅”,聊天窗口回复 “5369” 获取习题答案。

生信之巅微信公众号生信之巅小程序码

敬告:使用文中脚本请引用本文网址,请尊重本人的劳动成果,谢谢!Notice: When you use the scripts in this article, please cite the link of this webpage. Thank you!

上一篇:
Shiny从入门到入定——3-在特别大的花园里面挖呀挖呀挖
下一篇:
16S扩增子测序及宏基因组测序
本文目录
本文目录