【问题标题】:renderPlot issue when rendering a list of plots渲染绘图列表时出现 renderPlot 问题
【发布时间】:2019-01-24 08:38:56
【问题描述】:

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

我发现了几个相关的问题 r-markdown-shiny-renderplot-list-of-plots-from-lapplyshiny-r-renderplots-on-the-fly 但对我的情况并没有真正的帮助。我希望我没有在某个地方错过一个好的答案(我认为这是因为我认为这不是一个罕见的用例)。

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

请参阅下面的示例应用程序。我通过让用户选择要显示的绘图数量来简化问题。然后,renderUI 函数有一个循环,在变量 p 中创建这些图,然后调用 renderPlot(p)。我假设 Shiny 做了一些缓存,并且由于某种原因无法识别循环中的 p 变化?!

我找到了一个解决方法,将 renderPlot(p) 替换为 do.call("renderPlot", list(expr = 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)

【问题讨论】:

  • 我认为这是一个 pre-Shiny 问题。该方法可能会覆盖前一个图形设备。从某种意义上说,每个设备都可能被渲染,但只有几分之一秒,因为它被后续调用替换,并且只有最后一次调用不会被覆盖。
  • 例如:png("example.png"); for (p in seq_along(graphs)) {print(p)}; dev.off() - 我怀疑example.png 只会包含图表列表中的最终图表。
  • 嗨,乔恩,感谢您的 cmets。我认为您的解释不适用于此问题,因为 ggplot 不绘制任何东西(与 png() 不同),而是创建了一个必须由 renderPlot 渲染的 ggplot 对象。另外我不明白为什么 do.call 版本应该工作呢?

标签: r ggplot2 shiny


【解决方案1】:

我同意@JonMinton,我也遇到了同样的问题。我发现,当我重用相同的变量来保存绘图并渲染它们(例如你对 p 所做的事情)时,绘图会被下一个绘图覆盖,并且只有最终绘图会像你说的那样被复制 n 次。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2016-01-25
    • 2019-07-22
    • 2020-09-30
    • 2013-07-30
    • 1970-01-01
    • 2021-01-25
    相关资源
    最近更新 更多