【问题标题】:R Shiny: create reactiveValues object with input$ valuesR Shiny:使用 input$ 值创建 reactiveValues 对象
【发布时间】:2019-03-03 22:47:57
【问题描述】:

我想在 Shiny 中创建一个 reactiveValues 对象,其内容定义为输入小部件中包含的值。我设法做到了,但我的实现似乎不必要地笨拙:

  1. 创建一个空的reactiveValues 对象
  2. 当输入小部件的值随着observeEvent变化时监控
  3. 使用来自输入小部件 (isolate) 的非反应性值将值分配给 reactiveValues 对象

这是一个例子:

ui <- fluidPage(
    fluidRow(
        column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
        column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
        column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
    ),
    verbatimTextOutput("myorder")
)

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

    # 1. Create reactiveValues object
    menuR <- reactiveValues()

    # 2. Update values whenever widgets change
    observeEvent(c(input$main, input$desert),
        menuR[["meal"]] <- paste(c(isolate(input$main), isolate(input$desert)), collapse = " & ")
    )

    # 3. Perform operations on object values
    observeEvent(input$extra,
        menuR[["meal"]] <- paste0(toupper(menuR[["meal"]]), "!!!")
    )

    output$myorder <- renderText(menuR[["meal"]])
}

shinyApp(ui, server)

我非常想像这样直接创建reactiveValues对象(大大简化了上面的代码):

# Set values upon creation
menuR <- reactiveValues(meal = paste(c(input$main, input$desert), collapse = " & "))

这不起作用,因为input$main 是被动的...

我猜想用从小部件获得的值定义 reactiveValues 对象将是一种常见的做法。

我错过了什么吗?

感谢您的帮助,

雨果

【问题讨论】:

  • 为什么一定要使用reactiveValue?在您的情况下,只需将input$maininput$desert 放入renderText 就可以了。
  • 嗨,吉姆。我在现实世界的应用程序中的意图是让reactiveValuesobject 成为一个数据框,其内容可以通过几个小部件的输入即时修改。文本示例是一种简化。

标签: r shiny shiny-reactivity


【解决方案1】:

您可以使用reactive() 而不是reactiveValues() 来做到这一点。 menuR 是一个响应式对象,它依赖于maindesert 的输入值。定义后,您可以通过在服务器代码中调用 menu() 来使用它。此外,这使您免于使用isolate(),因为您可以将menu 的值设置为observeEvent() 内的反应对象。

library(shiny)

ui <- fluidPage(
  fluidRow(
    column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
    column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
    column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
  ),
  verbatimTextOutput("myorder")
)

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

  menuR <- reactive({
    paste(c(input$main, input$desert), collapse = " & ")
  })

  observeEvent(
    input$extra,
    menuR <- reactive({
      toupper(paste(c(input$main, input$desert), collapse = " & "))
    })
  )

  output$myorder <- renderText(menuR())

}

shinyApp(ui, server)

编辑

我之前误解了这个问题。您可以使用eventReactive() 来监视输入并在用户输入更改时更改。我还为用户尚未单击操作按钮时添加了默认值。

library(shiny)

ui <- fluidPage(
  fluidRow(
    column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
    column(2, radioButtons("desert", label = "Desert", choices = list("fruit", "cake"))),
    column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
  ),
  verbatimTextOutput("myorder")
)

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

  # Set a 'default' value for the output
  default.menuR <- reactive({
    paste(c(input$main, input$desert), collapse = " & ")
  })

  menuR <- eventReactive(input$extra, {
    toupper(paste(c(input$main, input$desert), collapse = " & "))
  })

  # Initial state of the button is 0, which displays 'default' value
  output$myorder <- renderText({
    if (input$extra == 0) {
      return(default.menuR())
    }
    menuR()
  })

}

shinyApp(ui, server)

希望这会有所帮助!

【讨论】:

  • 谢谢 Vishesh。不幸的是,我还要求反应对象可以通过几个小部件动态修改,而您的代码没有这样做(应用程序从不显示toupper() 生成的大写文本)。我相信这是因为包含大写文本的menuR 对象只存在于observeEvent 函数中。
  • 请让我知道编辑后的解决方案是否适合您。
  • 是的。谢谢 Vishesh。
【解决方案2】:

我已经采纳了 Vishesh 的建议并将其付诸实施。它看起来和我原来的例子没什么不同,仍然需要重复几行代码。 每次其中一个小部件发生变化时,它都会覆盖响应式对象。

library(shiny)

ui <- fluidPage(
    fluidRow(
        column(2, radioButtons("main", label = "Main dish", choices = list("salad", "pasta"))),
        column(2, radioButtons("dessert", label = "dessert", choices = list("fruit", "cake"))),
        column(8, actionButton("extra", "Louder!", style="background-color: #ffdb99"))
    ),
    verbatimTextOutput("myorder")
)

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

    menuR <- reactive({
        paste(c(input$main, input$dessert), collapse = " & ")
    })

    # Render text when app loads
    output$myorder <- renderText(menuR())

    # Update reactive object and re-render text (button 'extra')
    observeEvent(
        input$extra,{
            temp <- toupper(paste(c(input$main, input$dessert), collapse = " & "))
            menuR <<- reactive(temp)
            output$myorder <- renderText(menuR())
        }
    )

    # Update reactive object and re-render text (button 'main' or 'dessert')
    observeEvent(c(input$main, input$dessert),{
        menuR <- reactive(paste(c(input$main, input$dessert), collapse = " & "))
        output$myorder <- renderText(menuR())
    })

}

shinyApp(ui, server)

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 2020-07-02
    相关资源
    最近更新 更多