渲染图列表时的renderPlot问题

时间:2018-08-17 10:09:38

标签: r ggplot2 shiny

我正在编写一个R Shiny应用程序,该应用程序应允许用户创建一些数据的可自定义图。这个想法是我的应用程序提供了一个“创建新图”按钮,该按钮可以绘制图并将其存储在反应式中。 renderUI函数“监视”此列表并渲染该反应式中的所有图。

我发现了两个相关的问题r-markdown-shiny-renderplot-list-of-plots-from-lapplyshiny-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)

1 个答案:

答案 0 :(得分:0)

我同意@JonMinton,并且遇到了同样的问题。我发现当我重复使用相同的变量来保存图并渲染它们时(例如,对p所做的操作),下一个图将覆盖这些图,并且仅复制最终的图n次,如您所说。 / p>

要解决此问题,我为每个图定义了一个新变量,这对于您的项目可能不是可持续的,但这是一种解决方法。