我想在Shiny应用程序中插入非预定义数量的图形。我使用for循环和一系列insertUI。
当我运行它时,文本元素的行为符合预期,但是图形都呈现相同的图像。我该如何预防?
这里是一个代表:
library(shiny)
ui <- fluidPage(
tags$div(
class = "this",
actionButton("go", "go")
)
)
server <- function(input, output, session) {
observeEvent( input$go , {
x <- reactiveValues(x = list(iris, mtcars, airquality))
for (i in 1:3){
insertUI(
".this",
ui = tagList(
p(paste("Number", i)),
renderPlot({
plot(x$x[[i]])
})
))
}
})
}
shinyApp(ui, server)
答案 0 :(得分:4)
因此,找到了我自己的问题的答案-使用lapply()
可以完成这项工作:
library(shiny)
ui <- fluidPage(
tags$div(
class = "this",
actionButton("go", "go")
)
)
server <- function(input, output, session) {
observeEvent( input$go , {
x <- reactiveValues(x = list(iris, mtcars, airquality))
lapply(1:3, function(i){
insertUI(
".this",
ui = tagList(
p(paste("Number", i)),
renderPlot({
plot(x$x[[i]])
})
))
})
})
}
shinyApp(ui, server)
答案 1 :(得分:2)
当心for循环中的闭包;)。 R中没有块作用域,因此每个for循环迭代共享相同的迭代器变量i
。 renderXX
函数实际上存储的不是立即求值的表达式,而只是在以后需要渲染时才求值。
因此,在准备绘制图形时,已经完成了for循环,i
现在为3,每个plot(x$x[[i]])
表达式都称为plot(x$x[[3]])
。
您可以通过使用local()
或函数为每个循环迭代创建一个新的作用域来解决此问题。我最喜欢的解决方案是使用lapply
,以i
作为函数作用域变量在函数中运行每个循环迭代。
许多没有块范围的语言都具有相同的陷阱,例如Python和JS: