如何在循环中而不是单独使用函数来呈现组件

时间:2019-07-29 12:01:04

标签: r shiny

我有几个变量,每个变量都有一个值,我在R Shiny应用程序中使用valueBox显示这些变量。变量名称是固定的,但是值可以变化。

以下是一些虚拟数据来说明我的问题:

variable <- c("a", "b", "c", "d", "e")
value <- c(5, 120, -1/3, 67, 2)  
df <- data.frame(variable, value)

这是闪亮的应用程序代码,可提供所需的输出。

library(shiny)
library(shinydashboard)

ui <- dashboardPage(

  dashboardHeader(title = "Test App"),

  dashboardSidebar(),

  dashboardBody(
    fluidRow(valueBoxOutput("value_box_a")),
    fluidRow(valueBoxOutput("value_box_b")),
    fluidRow(valueBoxOutput("value_box_c")),
    fluidRow(valueBoxOutput("value_box_d")),
    fluidRow(valueBoxOutput("value_box_e"))
  )

  )

server <- function(input, output) {

  variable <- c("a", "b", "c", "d", "e")
  value <- c(5, 120, -1/3, 67, 2)

  df <- data.frame(variable, value)

  output$value_box_a <- renderValueBox({
    valueBox("a", df$value[df$variable == "a"])
    })

  output$value_box_b <- renderValueBox({
    valueBox("b", df$value[df$variable == "b"])
  })

  output$value_box_c <- renderValueBox({
    valueBox("c", df$value[df$variable == "c"])
  })

  output$value_box_d <- renderValueBox({
    valueBox("d", df$value[df$variable == "d"])
  })

  output$value_box_e <- renderValueBox({
    valueBox("e", df$value[df$variable == "e"])
  })

}

shinyApp(ui, server)

这是所需的输出: desired output

我没有单独渲染所有valueBox,而是尝试在循环中使用一个函数。考虑到它们之间的相似性,这似乎是有道理的。

这是我的尝试,不起作用:

library(shiny)
library(shinydashboard)

ui <- dashboardPage(

  dashboardHeader(title = "Test App"),

  dashboardSidebar(),

  dashboardBody(
    fluidRow(valueBoxOutput("value_box_a")),
    fluidRow(valueBoxOutput("value_box_b")),
    fluidRow(valueBoxOutput("value_box_c")),
    fluidRow(valueBoxOutput("value_box_d")),
    fluidRow(valueBoxOutput("value_box_e"))
  )

  )

server <- function(input, output) {

  variable <- c("a", "b", "c", "d", "e")
  value <- c(5, 120, -1/3, 67, 2)

  df <- data.frame(variable, value)

  for (var_name in variable) {
    output[[paste0("value_box_",var_name)]] <- renderValueBox({
      valueBox(var_name, df$value[df$variable == var_name])
    })
  }

}

shinyApp(ui, server)

这是我尝试的输出:

my attempt

任何人都可以建议如何实现我想要的吗?

1 个答案:

答案 0 :(得分:2)

这是一个棘手的错误。发生这种情况的原因是,Shiny(缺乏更好的语言)不会像我们习惯的那样执行代码,而是以某种方式存储了代码的缓存。

解决方案是通过将Shiny分配给新变量来强制Shiny为每个循环评估var_name的内容:

  for (var_name in variable) {
    local({            ## here
      v1 <- var_name   ## here
      output[[paste0("value_box_",var_name)]] <- renderValueBox({
          valueBox(v1, df$value[df$variable == v1])
      })
    })                 ## and closing here
  }

您还可以使用insertUI加倍创建动态控件。然后,您不必在ui中创建valueBoxOutput,而只需从server即时创建它们即可。