后起之秀奔涌而至,欢迎大家在《生信技能树》的舞台分享自己的心得体会!
上面是shiny团队的稿件
l4-反应输出
了解小工具如何和反应输出联系,反应输出即无何时用户改变小工具都会自动更新的对象
展示反应输出
是时候给app注入灵魂了,此篇介绍如何构建一个反应输出在app中展示。
只要用户触发小工具,反应输出会自动响应
如下图,右边的两行文字会根据用户对小工具的操作改变
此篇创建一个名为census-app的app
总的两步
可以通过两步处理构建反应输出
- 加一个R对象到你的用户界面
- 告诉shiny如何在
server
函数构建对象,该对象会在它的代码构建一个小工具的值的时候反应
第一步:加一个R对象到UI
shiny提供了一个函数家族,将R对象转换成在UI中的输出,每个函数创建特定类型的输出
你能加输出到UI就像加HTML元素和widgets一样。将输出函数放在ui对象中的sidebarPanel
和mainPanel
。
例如,下面的ui对象使用textOutput 加反应文本行到上图app的主面板
代码语言:javascript复制ui <- fluidPage(
titlePanel("censusVis"),
sidebarLayout(
sidebarPanel(
helpText("Create demographic maps with
information from the 2010 US Census."),
selectInput("var",
label = "Choose a variable to display",
choices = c("Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"),
selected = "Percent White"),
sliderInput("range",
label = "Range of interest:",
min = 0, max = 100, value = c(0, 100))
),
mainPanel(
textOutput("selected_var")
)
)
)
可以注意到textOutput采用了一个字符串"selected_var"作为参数。每个*Output函数都需要一个参数:一个app将用作反应元素的名字的字符串。用户不可见,但后面会用到
第二步:提供构建对象的R代码
在ui中放一个函数告诉app在何处放置你的对象。接下来,需要告诉shiny如何构建对象
就是在server函数中提供构建对象的R代码
server函数在shiny的处理中扮演一个特别的角色,他会构建一个类似列表(list)的对象,被命名为output,包含所有用来更新app中R对象的代码,每个R对象在list中要有自己的条目(名字)
在server函数中,可以通过在output定义一个新元素来创建条目,如下,元素名字应该与ui中反应元素使用的参数一致
就像此处
output$selected_var 匹配ui中的 textOutput("selected_var")
代码语言:javascript复制server <- function(input, output) {
output$selected_var <- renderText({
"You have selected this"
})
}
在server中无需其他代码用来返回output的值,R将通过引用类语义(class semantics)自动更新output
output的条目都应该包含render* 函数家族中的某一个。这些函数捕捉R表达式,并进行一些渲染预处理,每个render*函数对应特定类型的反应对象,如下表
每个render *函数都有一个参数:一个用大括号{}
括起来的R表达式。表达式可以是一行简单的文本,也可以包含很多行代码,就像是一个复杂的函数调用一样。
将此R表达式视为一组指令,您可以将它们提供给Shiny以便以后存储。首次启动应用程序时,Shiny会运行说明,然后每次需要更新对象时,Shiny都会重新运行说明。
将R表达式视为稍后于shiny的一组指令,当首次启动app时,shiny会运行这个指令,当每次需要更新对象时,shiny也会重新运行这个指令。
因此,表达式应该返回你期望的对象(文本,图,数据框等),当表达式不返回对象或错误的对西那个类型时会报错
使用小工具(widget)的值
当用上面的代码构建app后,会发现app长这样
文本不会对小工具作出反应
那应该怎么做呢
通过在构建文本时,让shiny调用小工具的值,从而实现文本反应
看一下代码发现,server函数的第一行有两个参数input和output
已知output是个列表类的对象,储存构建app中对象的指令
input是第二个列表类对象,会存储所有小工具的所有当前值,这些值会存在ui中对应的小工具中给出的name名下
例中app有两个小工具,一个name是"var",一个name是"range", 他们的值将分别存在input
range。因为滑块小工具有两个值,最大值和最小值,所以input$range 会包含一个长度为二的向量。
Shiny会自动让一个包含input值的对象反应,例如下面的server函数通过选择框小部件构建的文本,创建一个反应文本行
代码语言:javascript复制server <- function(input, output) {
output$selected_var <- renderText({
paste("You have selected", input$var)
})
}
shiny 追踪哪个输出取决于是哪个小工具。
当用户改变小工具,shiny会使用新的值重建依赖于那个小工具的所有的输出,重建对象达到更新的目的
这就是如何用shiny创建反应,通过连接input列表中的值到output中的对象。shiny自动处理其他细节
启动你的应用看看反应输出
将上面的代码放到你的app中,可以使用runApp("census-app", display.mode = "showcase")运行app
看起来像下图,操作选择框的时候文本也会随之改变
在改变的时候,反应部分的代码甚至会变黄,有助于理解反应输出
练习
在上面的App加第二行反应文本,加到app的主面板,展示如 “You have chosen a range that goes from something to something” 其中something对应最大值和最小值
小提示,ui和server要都更新哦(记得一定要先自己做哦,不偷看答案)
回顾
- 构建了第一个有灵魂的(能反应的)app
- 在server中使用render*函数告诉Shiny如何构筑你的对象
- 在每个render*函数中,用{}抱住R表达式
- 将render* 表达式的结果保存到output列表,每个反应对象对应其中的一个条目
- 通过在render*中的表达式包含一个input值来创建反应对象
我的结果( ?又对了)
我的代码
代码语言:javascript复制library(shiny)
ui <- fluidPage(
titlePanel("censusVis"),
sidebarLayout(
sidebarPanel(
helpText("Create demographic maps with
information from the 2010 US Census."),
selectInput("var",
label = "Choose a variable to display",
choices = c("Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"),
selected = "Percent White"),
sliderInput("range",
label = "Range of interest:",
min = 0, max = 100, value = c(0, 100))
),
mainPanel(
textOutput("selected_var"),
textOutput("maxandmin")
)
)
)
server <- function(input, output) {
output$selected_var <- renderText({
paste("You have selected", input$var)
})
output$maxandmin <- renderText({
paste("You have chosen a range that goes from", input$range[1], "to", input$range[2])
})
}
shinyApp(ui = ui,server = server)
参考答案
代码语言:javascript复制library(shiny)ui <- fluidPage(titlePanel("censusVis"),
sidebarLayout(sidebarPanel(helpText("Create demographic maps with
information from the 2010 US Census."),
selectInput("var",
label = "Choose a variable to display",
choices = c("Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"),
selected = "Percent White"),
sliderInput("range",
label = "Range of interest:",
min = 0, max = 100, value = c(0, 100))),
mainPanel(textOutput("selected_var"),
textOutput("min_max"))))
server <- function(input, output) {
output$selected_var <- renderText({paste("You have selected", input$var)})
output$min_max <- renderText({paste("You have chosen a range that goes from",
input$range[1], "to", input$range[2])})
}
shinyApp(ui, server)
Reference:
Shiny - Display reactive output