在ObserveEvent中生成图形(动态绘图)

3

我正在尝试通过添加按钮来重新创建https://gist.github.com/wch/5436415/中的图表。我认为这需要我按照以下方式修改链接中的server.r代码(与图表名称相关的变量是通过reactiveValues创建的)-

observeEvent(
      input$buttonAddData, 
      {
         ...
         newchartname = c(newchartname,newchartname)
         output[[newchartname]] = renderPlot({
            ...
         })
      }
)

output$plots = renderUI(
      {

         plot_output_list <- lapply(
            seq(length(allthechartnames)), 
            function(i) {
               plotname <- paste(
                  isolate(allthechartnames)[i]
               )
               plotOutput(plotname, height = 280, width = 250)
               cat(plotname,'\n')
            }
         )

         # Convert the list to a tagList - this is necessary for the list of items
         # to display properly.
         do.call(tagList, plot_output_list)

      }
   )

但是在observeEvent中似乎没有进入创建图表的原始循环,这导致在renderUI块中没有图表。

有什么建议吗?


2
不应该在观察器内调用渲染函数。相反,应该在观察器中使用reactiveValues,改变响应式值的值,并将该值作为渲染函数的依赖项。 - DeanAttali
@daattali - 在上述代码中,我尝试向reactivevalues列表(称为<chartname>)添加元素,并将在observe内部创建的图表分配给它。 我不确定如何在渲染处进行替换。 我无法执行plotname = <listofreactivevalues>$<chartname> - TheComeOnMan
如果您能提供可工作的代码而不是片段,那么理解问题/解决方案可能会更容易。 - DeanAttali
我正在尝试做类似于这个链接的东西 = https://gist.github.com/wch/5436415/,但是我想要一个生成随机数据并为每个随机数据生成一个图表的按钮,而不是一个定义好的滑块。这有帮助吗?如果不行,请告诉我,我会编写我的代码版本并在问题上发布它。 - TheComeOnMan
1个回答

8

我并不真正理解您问题中的代码,因此我忽略了它,只是采用了Winston在gist中的代码,并使其适用于按钮而不是滑块。希望这符合您的意愿?此外,我确实不得不在观察器内使用渲染,这让我感到不太满意 :/

runApp(shinyApp(
  ui = fluidPage(
    headerPanel("Dynamic number of plots"),

    mainPanel(
      actionButton("addplot", "Add plot"),
      uiOutput("plots")
    )
  ),
  server = function(input, output, session) {

    # A variable that keeps track of the number of plots we have
    values <- reactiveValues(
      numPlots = 1
    )

    # Whenever the "add plot" button is pressed, increment num plots by 1
    observeEvent(input$addplot, {
      values$numPlots <- values$numPlots + 1
    })

    # Dynamically generate the UI that creates all the plots
    output$plots <- renderUI({
      # Create a list of `plotOutput` objects (for each plot, use a unique ID)
      plot_output_list <- lapply(1:values$numPlots, function(i) {
        plotname <- paste("plot", i, sep="")
        plotOutput(plotname, height = 280, width = 250)
      })

      # Place all the plot outputs inside a shiny `tagList()`
      do.call(tagList, plot_output_list)
    })

    # Every time the number of plots changes (button is clicked),
    # re-generate the render functions for all the plots
    observeEvent(values$numPlots, {
      for (i in 1:values$numPlots) {
        local({
          my_i <- i
          plotname <- paste("plot", my_i, sep="")

          output[[plotname]] <- renderPlot({
            plot(1:my_i, 1:my_i,
                 xlim = c(1, values$numPlots),
                 ylim = c(1, values$numPlots),
                 main = paste("1:", my_i, ".  n is ", values$numPlots, sep = "")
            )
          })
        })
      }
    })
  }
))

希望这能帮到你。

我尝试运行它,但它说找不到max_plots。我的确需要一个按钮来完全克服max_plots的需求。我可能有10个图,也可能有100个,我不知道。 - TheComeOnMan
糟糕,我的错,忘记在干净的会话上运行它了。现在应该可以工作了。 - DeanAttali
我的代码中没有 max_plots,而是使用了一个反应式值。我不太确定我理解那个问题。 - DeanAttali
使用本地变量并不是坏事(至少据我所知)——在观察器内部使用渲染器是不可取的,据我所知。我相信我看到过 Shiny 的两位作者之一 Joe Cheng 和 Winston Chang 多次提到这一点,尽管我可能错了。虽然也许我错了,也许他们说在reactive内部使用渲染器是不好的(我可以理解为什么不好,因为反应式值可以缓存,你不想在其中产生副作用)。 - DeanAttali
我问了“max_plots”的问题,但是后来我试了一下。我不需要一个观察器来增加值并在循环中添加图表,我在第一个观察器内部进行随机数据生成并在那里添加图表。我也理解反应式中副作用的可能性。感谢您抽出时间! - TheComeOnMan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接