渲染打印列表时的renderPlot问题

渲染打印列表时的renderPlot问题,r,ggplot2,shiny,R,Ggplot2,Shiny,我正在写一个R闪亮的应用程序,它应该允许用户创建一些数据的可定制绘图。我的想法是,我的应用程序提供了一个“创建新绘图”按钮,该按钮可以渲染绘图并将其存储在一个反应式窗口中。renderUI函数“监视”此列表并呈现该列表中的所有绘图 我发现了一些相关的问题,但对我的情况并没有真正的帮助。我希望我没有在某个地方错过一个好的答案(我认为会有,因为我认为这不是一个罕见的用例) 在实现时,我注意到一个奇怪的行为:当只显示一个情节时,一切都正常。但是,当我有n(n>1)个绘图时,应用程序只显示了绘图n的n倍

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

我发现了一些相关的问题,但对我的情况并没有真正的帮助。我希望我没有在某个地方错过一个好的答案(我认为会有,因为我认为这不是一个罕见的用例)

在实现时,我注意到一个奇怪的行为:当只显示一个情节时,一切都正常。但是,当我有n(n>1)个绘图时,应用程序只显示了绘图n的n倍,而不是渲染绘图1、绘图2、…、绘图n

请参阅下面我的示例应用程序。我简化了这个问题,只让用户选择要显示的图的数量。然后,renderUI函数有一个循环,在变量p中创建thees图,然后调用renderPlot(p)。我假设shiny进行了一些缓存,但由于某种原因,无法识别循环中的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)
库(闪亮)
图书馆(GG2)
#定义用户界面

ui我同意@JonMinton,我也有同样的问题。我发现,当我重复使用同一个变量来保存和渲染绘图时(比如你用p所做的),绘图会被下一个绘图覆盖,只有最后的绘图会像你说的那样被复制n次


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

我认为这是一个预先解决的问题。这种方法可能会覆盖上一个图形设备。从某种意义上说,每个设备都可以渲染,但当它被su替换时,只需几秒钟b连续调用,并且只有最后一个调用不会被覆盖。例如:
png(“example.png”);For(沿(图)的顺序中的p){print(p)};dev.off()
-我怀疑
example.png
只包含图形列表中的最后一个图形。嗨,Jon,谢谢你的评论。我认为你的解释不适用于这个问题,因为ggplot不绘制任何图形(不像png()但是创建了一个必须由renderPlot渲染的ggplot对象。我也不明白为什么do.call版本应该工作?