echarty icon indicating copy to clipboard operation
echarty copied to clipboard

Changing result based on legend selection

Open helgasoft opened this issue 3 years ago • 0 comments

This is an interesting question by @ddrogen asked here. Specifically, how to change some series data live just by toggling legend items ? Since the need is to update a chart in real time without Shiny, then obviously some Javascript code has to be written. Here is one solution which relies on additional data preparation and ECharts event handling.

set.seed(222)    # make the chart reproducible
library(dplyr)
data2 <- data.frame(zipcode= as.factor(round(rnorm(10, 87965, 50),0)), program_1 = rnorm(10, 200, 20), program_2 = rnorm(10, 700, 100), program_3 = rnorm(10, 500, 50))
data1 <- data2 %>% 
  mutate(total = rowSums(across(where(is.numeric)))) %>%
  mutate(A= round(100*program_1/total,1)) %>%
  mutate(B= round(100*program_2/total,1)) %>%
  mutate(C= round(100*program_3/total,1)) %>%
     #  additional data to cover all combinations
  mutate(AB= round(100*(program_1+program_2)/total,1)) %>%   
  mutate(AC= round(100*(program_1+program_3)/total,1)) %>%
  mutate(BC= round(100*(program_2+program_3)/total,1)) %>%

  mutate("per_total"= 100*total/sum(total)) %>%
  arrange(desc(total)) %>%
  mutate(ABC = round(cumsum(per_total),1))  # renamed from 'cum_sum_total'

library(echarty)
p <- data1 |> ec.init(elementId='cid', 
                     legend= list(show=TRUE),  
    xAxis= list(name = "Zip Code",
      nameLocation = "middle", nameGap=50,
      nameTextStyle = list(color = "#87786B", fontSize = 15), 
      axisLabel = list(fontFamily="Arial",
                       interval = 0, rotate = 30,
                       fontSize=12, color="#87786B")),
    yAxis= list(
      list(name="n° of visits", index = 0, show = TRUE, 
           nameLocation ="middle",
           nameGap=70, align="right", 
           nameTextStyle = list(
             color = "#87786B",
             fontSize = 12),
           axisLabel = list(fontSize=12, color="#87786B")), 
      list(name= '%') ),
    series= list(
           list(name='A', type='bar', encode=list(x='zipcode', y='program_1'), stack='g'), 
           list(name='B', type='bar', encode=list(x='zipcode', y='program_2'), stack='g'),
           list(name='C', type='bar', encode=list(x='zipcode', y='program_3'), stack='g'),
           list(name = "Cumulative %", type='line', encode=list(x='zipcode', y='ABC'), 
                 yAxisIndex= 1, emphasis= list(focus= "series"),
                 label= list(
                        show= TRUE, 
                        textStyle = list(fontFamily = "Arial", fontSize = 10))) ),
    tooltip= list(formatter = htmlwidgets::JS("function(params) {
      col = 'ABC'.indexOf(params.seriesName) +1;
      return(params.marker + params.seriesName +
       '<br> Total: ' + params.value[col].toFixed(2) + ' (' +
                                         params.value[col+4] + '%)');}"),
                   textStyle= list(fontFamily="Arial", fontSize=12)),
    animationDuration= 1500,
    toolbox= list(show =TRUE, top=0, right= 10, itemSize=10, 
                  emphasis= list(iconStyle= list(textFill= "#6C2C4E")),
                  feature = list(restore=list(show=TRUE), saveAsImage=list(show=TRUE)) )
)  |> 
ec.theme('t1', code='{"color": ["#F8AD3B", "#D15425", "#9CAC3B", "#6C2C4E"]}')
p$x$on <- list(list(event= 'legendselectchanged', 
      handler= htmlwidgets::JS("function(v) { 
      sel = v.selected;
      chart = get_e_charts('cid'); 
      opt = chart.getOption();
      vals = Object.values(sel).slice(0,3);
      nams = Object.keys(sel).slice(0,3);
      col= ''; i= 0;
      vals.map(x => {if (x) col= col + nams[i]; i++;});
      if (col != '')
         opt.series[3].encode.y = col;  // A or AC or ABC etc.
      chart.setOption(opt, true);  // replace chart
    }")
))
p

https://user-images.githubusercontent.com/13038071/187005714-ce02a9aa-787a-40d4-ae68-9652bf32c648.mp4

Note: if you like this solution, please consider granting a Github star ⭐ to echarty.

helgasoft avatar Aug 27 '22 00:08 helgasoft