如何使用 futures 逐个渲染每个图而不是同时渲染所有图?

问题描述 投票:0回答:1

我有一个闪亮的应用程序,它使用一个函数来生成 N 个绘图(在本例中为 10 个)。

我不是使用地图同时创建所有 10 个图表,而是尝试使用 futures 包在每个绘图准备就绪时将其一一渲染。

library(shiny)
library(plotly)
library(purrr)
library(future)
library(promises)

# Enable parallel processing
plan(multisession)

# Generate 10 titles
titles <- paste0("Chart", 1:10)

# Create the list of lists
charts <- map(titles, ~ list(title = .x)) %>%
  setNames(titles)

chart_func <- function(title) {
  Sys.sleep(runif(1, 0.5, 2))  # Simulate some computation time
  plotly::plot_ly() %>%
    layout(
      title = title
    )
}

ui <- fluidPage(
  actionButton("make_plots", "Make Plots"),
  uiOutput("all_plots")
)

server <- function(input, output, session) {
  
  # Define plot names
  plot_names <- names(charts)
  
  # Render the UI with placeholders for all plots
  output$all_plots <- renderUI({
    purrr::map(plot_names, ~tags$div(class = "single-plot", plotlyOutput(.x)))
  })
  

  # Generate plots asynchronously upon button click
  observeEvent(input$make_plots, {
    
    map(charts, function(chart) {
      future({
        chart_func(chart$title)
      }, seed = TRUE) %...>% { result ->
        output[[chart$title]] <- renderPlotly({
          result
        })
      }
    })
    
  })
}

shinyApp(ui, server)

这段代码很接近,但我遇到错误并且不确定下一步要尝试什么。我知道方法链接是正确的,我只需要一些输出方面的帮助。

r shiny parallel-processing
1个回答
0
投票
library(shiny)
library(plotly)
library(purrr)
library(future)
library(promises)
library(bslib)

# Enable parallel processing
plan(multisession)

# Generate 10 titles
titles <- paste0("Chart", 1:10)

# Create the list of lists
charts <- map(titles, ~ list(title = .x)) %>%
  setNames(titles)

chart_func <- function(title) {
  Sys.sleep(runif(1, 0.5, 2))  # Simulate some computation time
  plotly::plot_ly(type = "scatter", mode = "markers") %>%
    layout(
      title = title
    )
}

ui <- fluidPage(
  input_task_button("make_plots", "Make Plots"),
  uiOutput("all_plots")
)

server <- function(input, output, session) {
  # Define plot names
  plot_names <- names(charts)
  
  compute_plot <- ExtendedTask$new(function(chart) {
    future_promise({
      list(title = chart$title, plotly_obj = chart_func(chart$title))
    }, seed = TRUE)
  }) |> bind_task_button("make_plots")
  
  # Render the UI with placeholders for all plots
  output$all_plots <- renderUI({
    purrr::map(plot_names, ~tags$div(class = "single-plot", plotlyOutput(.x)))
  })
  
  # Generate plots asynchronously upon button click
  observeEvent(input$make_plots, {
    map(charts, function(chart) {
      compute_plot$invoke(chart)
    })
  })
  
  observeEvent(compute_plot$result(), {
    output[[compute_plot$result()$title]] <- renderPlotly({
      isolate(compute_plot$result()$plotly_obj)
    })
  })
}

shinyApp(ui, server)

请查看这篇相关文章

© www.soinside.com 2019 - 2024. All rights reserved.