在延迟表达式评估中,R Shiny使用变量的变量值

时间:2018-01-07 08:11:43

标签: r shiny

以下是该问题的简单演示:

library(shiny)

ui <- fluidPage(
    textOutput("Text1"),
    textOutput("Text2")
)

server <- function(input, output) {
    for(i in 1:2) {
        id <- paste0("Text", i)
        output[[id]] <- renderText(paste0("This is text #", i)) # Problem!
    }
}

shinyApp(ui, server)

该程序产生输出

这是文字#2
这是文本#2

而不是#1和#2。

显然,Shiny将传递给renderText()的表达式存储在标记为#Problem!的行中,并在 for循环完成后对它们进行评估。表达式取决于变量i,其最终值i = 2用于评估两个表达式。

如何生成正确的输出(如何强制Shiny在不同的表达式中使用i的不同值),同时仍然使用循环?在我的代码中,循环限制是动态的,我不能用几个静态调用替换循环。

1 个答案:

答案 0 :(得分:4)

为什么for - 循环不起作用,请检查此示例的输出:

library(shiny)

ui <- fluidPage(
  textOutput("Text1"),
  textOutput("Text2")
)

server <- function(input, output) {
  for(i in 1:3) {
    id <- paste0("Text", i)
    output[[id]] <- renderText(paste0("This is text #", i)) # Problem!
  }
  i=10 # we set i to 10.

}

shinyApp(ui, server)

如您所见,所有renderText元素都使用i的最后一个(全局)值。 lapply中的情况并非如此,其中参数传递给函数,但该参数未在全局环境中定义。

所以你可以使用lapply而不是for - 循环,如下所示:

library(shiny)

ui <- fluidPage(
  textOutput("Text1"),
  textOutput("Text2")
)

server <- function(input, output) {

  lapply(1:2,function(i){
    id <- paste0("Text", i)
    output[[id]] <- renderText(paste0("This is text #", i)) # Problem!
  })

}

shinyApp(ui, server)

输出:

enter image description here

如果您还希望ui被动,您可以使用renderUIuiOutput,例如:

library(shiny)

ui <- fluidPage(
  numericInput("number_of_text","Number of text",min=1,max=10,value=3),
  uiOutput('my_text')
)

server <- function(input, output) {


  reactive_text <- reactive({
    all_text <- lapply(1:input$number_of_text,function(i){
      id <- paste0("Text", i)
      renderText(paste0("This is text #", i)) # Problem!
    })
   # do.call(all_text,tagList)
  })

  output$my_text <- renderUI({
    do.call(fluidRow, reactive_text())
  })

}

shinyApp(ui, server)

输出:

enter image description here

希望这有帮助!