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

基础UI

引言

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

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

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

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

1
library(shiny)

输入

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

常见结构

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

inputId有两个约束:

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

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

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

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

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

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

自由文本

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

1
2
3
4
5
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的数值向量,你将获得一个带有两个端点的“范围”滑块。

1
2
3
4
5
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

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

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

日期

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

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

date

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

有限制的选择

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

1
2
3
4
5
6
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函数中返回的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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以允许用户选择多个元素。

1
2
3
4
5
6
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()

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

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

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

文件上传

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

1
2
3
ui <- fluidPage(
fileInput("upload", NULL)
)

上传文件

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

动作按钮

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

1
2
3
4
5
6
7
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"使按钮跨越其嵌入的元素的整个宽度。

1
2
3
4
5
6
7
8
9
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()输出固定代码和控制台输出。

1
2
3
4
5
6
7
8
9
10
11
12
ui <- fluidPage(
textOutput("text"),
verbatimTextOutput("code")
)
server <- function(input, output, session) {
output$text <- renderText({
"Hello friend!"
})
output$code <- renderPrint({
summary(1:10)
})
}

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

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

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

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

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

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

1
2
3
4
5
6
7
8
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包。

1
2
3
4
5
6
7
8
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或其他)。

1
2
3
4
5
6
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/中的选项。

1
2
3
4
5
6
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扩增子测序及宏基因组测序