rshinyproxyecharts4r

Dynamic update of variable without redrawing the entire graph (proxy)


I am trying to display a graph using echarts4r in a Shiny application, where the user can adjust a dynamic threshold (Threshold).

I want only the "Threshold" series to update without redrawing the entire graph (i.e., the zoom level and other series should remain fixed).

I tried to use the poxy function from echarts4r, with no success.

Here is my code:

library(shiny)
library(echarts4r)
library(dplyr)


set.seed(123)
df <- data.frame(
  Date = seq(as.Date("2023-01-01"), by = "week", length.out = 104),
  Cas = sample(50:500, 52, replace = TRUE),
  Cas_A = sample(20:100, 52, replace = TRUE),
  Cas_B = sample(5:50, 52, replace = TRUE),
  Cas_C = sample(1:20, 52, replace = TRUE),
  Threshold = rep(200, 52) # Valeur initiale du seuil
)

ui <- fluidPage(
  titlePanel("TEST"),
  
  sidebarLayout(
    sidebarPanel(
      sliderInput("Percentile", "Threshold Value:", min = 1, max = 99, value = 50, step = 1)
    ),
    
    mainPanel(
      echarts4rOutput("Graph")
    )
  )
)
server <- function(input, output, session) {
 
   reactive_threshold <- reactive({
  perc <- input$Percentile

  perc_threshold <- quantile(df$Cas, probs = perc / 100, na.rm = TRUE)
  
  cdc_nat_threshold <- df %>%
    mutate(Threshold = perc_threshold)  
  return(cdc_nat_threshold)
  
})
  

  output$Graph <- renderEcharts4r({
    reactive_threshold() |>
      e_charts(Date) |>
      e_line(Cas, name = "Cas", lineStyle = list(color = "#ff8000", width = 2, opacity = 0.4)) |>
      e_bar(Cas_A, name = "Cas_A", stack = "group", itemStyle = list(color = "#C1D8C3")) |>
      e_bar(Cas_B, name = "Cas_B", stack = "group", itemStyle = list(color = "#6A9C89")) |>
      e_bar(Cas_C, name = "Cas_C", stack = "group", itemStyle = list(color = "#d63e0b")) |>
      e_line(Threshold, name = "Threshold", lineStyle = list(color = "#f02b2b", width = 1, type = "dashed", opacity = 0.8)) |>
      e_legend(show = TRUE) |>
      e_axis_labels(y = "Weekly") |>
      e_tooltip(trigger = "axis") |>
      e_datazoom(x_index = 0, toolbox = FALSE, start = 20, end = 50) |>
      e_group("shared_zoom") |>
      e_connect_group("shared_zoom")
  })
  

  observeEvent(input$Percentile, {
    echarts4rProxy("Graph") |>

      e_line(
 Threshold) |>
      e_execute()
  })
}

shinyApp(ui, server)

Solution

  • Perhpas this fits your need. First, to avoid that the entire chart gets redrawn when the reactive dataset changes, I wrap it in isolate(). Second, in the observeInit I pass the updated data to the data= argument of echarts4rProxy(). Additionally we have to set the x = Date. Next, we have to remove the existing series using e.g. e_remove_series and finally add a new line.

    library(shiny)
    library(echarts4r)
    library(dplyr)
    
    ui <- fluidPage(
      titlePanel("TEST"),
      sidebarLayout(
        sidebarPanel(
          sliderInput("Percentile", "Threshold Value:", min = 1, max = 99, value = 50, step = 1)
        ),
        mainPanel(
          echarts4rOutput("Graph")
        )
      )
    )
    
    server <- function(input, output, session) {
      reactive_threshold <- reactive({
        perc <- input$Percentile
    
        perc_threshold <- quantile(df$Cas, probs = perc / 100, na.rm = TRUE)
    
        cdc_nat_threshold <- df %>%
          mutate(Threshold = perc_threshold)
        return(cdc_nat_threshold)
      })
    
      output$Graph <- renderEcharts4r({
        isolate(
          reactive_threshold()
        ) |>
          e_charts(Date) |>
          e_line(Cas, name = "Cas", lineStyle = list(color = "#ff8000", width = 2, opacity = 0.4)) |>
          e_bar(Cas_A, name = "Cas_A", stack = "group", itemStyle = list(color = "#C1D8C3")) |>
          e_bar(Cas_B, name = "Cas_B", stack = "group", itemStyle = list(color = "#6A9C89")) |>
          e_bar(Cas_C, name = "Cas_C", stack = "group", itemStyle = list(color = "#d63e0b")) |>
          e_line(Threshold, name = "Threshold", lineStyle = list(color = "#f02b2b", width = 1, type = "dashed", opacity = 0.8)) |>
          e_legend(show = TRUE) |>
          e_axis_labels(y = "Weekly") |>
          e_tooltip(trigger = "axis") |>
          e_datazoom(x_index = 0, toolbox = FALSE, start = 20, end = 50) |>
          e_group("shared_zoom") |>
          e_connect_group("shared_zoom")
      })
    
      observeEvent(input$Percentile, {
        echarts4rProxy("Graph", data = reactive_threshold(), x = Date) |>
          e_remove_serie("Threshold") |>
          e_line(Threshold, name = "Threshold", lineStyle = list(color = "#f02b2b", width = 1, type = "dashed", opacity = 0.8)) |>
          e_execute()
      })
    }
    
    shinyApp(ui, server)