我正在编写一个R Shiny应用程序,该应用程序应允许用户创建一些数据的可自定义图。这个想法是我的应用程序提供了一个“创建新图”按钮,该按钮可以绘制图并将其存储在反应式中。 renderUI函数“监视”此列表并渲染该反应式中的所有图。
我发现了两个相关的问题r-markdown-shiny-renderplot-list-of-plots-from-lapply或shiny-r-renderplots-on-the-fly,但对我的情况并没有真正帮助。我希望我不会在某个地方错过一个好的答案(我想是因为我认为这不是一个罕见的用例)。
在实施时,我注意到了一个奇怪的行为:当只显示一个图时,一切正常。但是,当我有n(n> 1)个图时,而不是渲染图1,图2,...,图n,该应用程序仅显示n倍于图n。
请参阅下面的示例应用程序。我通过仅让用户选择要显示的地块数来简化了问题。然后,renderUI函数具有一个循环,该循环在变量p中创建thees图,然后调用renderPlot(p)。我假设发亮了一些缓存,并且由于某种原因无法识别循环中的p变化?!
我找到了一种解决方法,将do.call(“ renderPlot”,list(expr = p)替换了renderPlot(p),虽然可以完成这项工作,但我仍然很想知道为什么直接renderPlot无法正常工作。
这是我的示例应用程序:
library(shiny)
library(ggplot2)
# Define UI
ui <- shinyUI(fluidPage(
titlePanel("renderPlot Test"),
sidebarLayout(
sidebarPanel(
numericInput(inputId = "n", label = "Number of Plots", value = 1L, min = 1L, max = 5L, step = 1L),
checkboxInput(inputId = "use_do.call", label = "use 'do.call'", value = FALSE)
),
mainPanel(
uiOutput("show_plots")
)
)
))
# Define server logic
server <- shinyServer(function(input, output) {
output$show_plots <- renderUI({
ui <- tags$div(tags$h4("Plots"))
for( i in 1:input$n ) {
p <- ggplot() + ggtitle(paste("plot", i))
if( input$use_do.call ) { # this works
ui <- tagAppendChild(ui, do.call("renderPlot", args=list(expr=p, width = 200, height = 200)))
} else { # this doesn't ...
ui <- tagAppendChild(ui, renderPlot(p, width = 200, height = 200))
}
}
return(ui)
})
})
# Run the application
shinyApp(ui = ui, server = server)
答案 0 :(得分:0)
我同意@JonMinton,并且遇到了同样的问题。我发现当我重复使用相同的变量来保存图并渲染它们时(例如,对p所做的操作),下一个图将覆盖这些图,并且仅复制最终的图n次,如您所说。 / p>
要解决此问题,我为每个图定义了一个新变量,这对于您的项目可能不是可持续的,但这是一种解决方法。