查看原文
其他

基于R语言的shiny网页工具开发基础系列-04

The following article is from 生信技能树 Author 生信技能树

l4-反应输出

了解小工具如何和反应输出联系,反应输出即无何时用户改变小工具都会自动更新的对象

展示反应输出

是时候给app注入灵魂了,此篇介绍如何构建一个反应输出在app中展示。

只要用户触发小工具,反应输出会自动响应

如下图,右边的两行文字会根据用户对小工具的操作改变


此篇创建一个名为census-app的app

总的两步

可以通过两步处理构建反应输出

  • 加一个R对象到你的用户界面
  • 告诉shiny如何在server函数构建对象,该对象会在它的代码构建一个小工具的值的时候反应

第一步:加一个R对象到UI

shiny提供了一个函数家族,将R对象转换成在UI中的输出,每个函数创建特定类型的输出


你能加输出到UI就像加HTML元素和widgets一样。将输出函数放在ui对象中的sidebarPanelmainPanel

例如,下面的ui对象使用textOutput 加反应文本行到上图app的主面板

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(0100))
    ),
    
    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")

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", 他们的值将分别存在inputrange。因为滑块小工具有两个值,最大值和最小值,所以input$range 会包含一个长度为二的向量。


Shiny会自动让一个包含input值的对象反应,例如下面的server函数通过选择框小部件构建的文本,创建一个反应文本行

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值来创建反应对象

我的结果( 🤠又对了)


我的代码

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(0100))
    ),

    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)

参考答案

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(0100))),
    
    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


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存