dreamRs / apexcharter

:bar_chart: R Htmlwidget for ApexCharts.js
https://dreamrs.github.io/apexcharter
Other
138 stars 15 forks source link

Custom tooltip for stacked barcharts #29

Open u909090 opened 3 years ago

u909090 commented 3 years ago

Hi,

First of all, thanks for this awesome package ! However, I am having issues customizing the tooltip when making stacked barcharts.

From the example given in the vignette:

library(ggplot2)
library(scales)
library(dplyr)
library(apexcharter)

data("mpg")
n_manufac_year <- count(mpg, manufacturer, year) %>%
group_by(manufacturer) %>% 
mutate(pct = n/sum(n)*100)

apex(data = n_manufac_year, type = "column", mapping = aes(x = manufacturer, y = pct, fill = year)) %>% 
  ax_chart(stacked = TRUE)

How could one display tooltips formatted as below for instance (i.e. containing pct and n values):

dodge
1999: 43.2% (16)
2008: 56.8% (21)

I tried to include a custom formatter but I am afraid I do not get the JS logic

apex(data = n_manufac_year, type = "column", mapping = aes(x = manufacturer, y = pct, fill = year)) %>% 
  ax_chart(stacked = TRUE) %>%
  ax_tooltip(
     y = list(
      formatter = JS("function(value) {return value + '%'}")
    )
  )
pvictor commented 3 years ago

Hello,

Quick answer to help you (there's a point in your question that is more complicated, I'll respond later).

In your formatter JavaScript code, a semicolon is missing, e.g. :

JS("function(value) {return value + '%';}")

You can also customize numeric format in tooltip / axes with format_num() function, complete example:

library(ggplot2)
library(scales)
library(dplyr)
library(apexcharter)

data("mpg")
n_manufac_year <- count(mpg, manufacturer, year) %>%
  group_by(manufacturer) %>% 
  mutate(pct = n / sum(n)) # dont divide by 100

apex(data = n_manufac_year, type = "column", mapping = aes(x = manufacturer, y = pct, fill = year)) %>% 
  ax_chart(stacked = TRUE) %>% 
  ax_yaxis(
    max = 1,
    labels = list(
      formatter = format_num(".0%") # no decimal
    )
  ) %>% 
  ax_tooltip(
    y = list(
      formatter = format_num(".2%") # 2 decimals
    )
  )

The more complex things to do in tooltip is to add another value not used in chart, in your case the absolute value after the percentage. It would be a neat functionnality, I have to think how to implement this in a smart way.

Victor

u909090 commented 3 years ago

Thanks for your help Victor !

I see the trick. It seems to be possible in echarts4r, I was simply wondering if it followed the same logic here.

pvictor commented 3 years ago

You're welcome! No that's a little different in Apexcharts.

A solution in your case is to do:

apex(
  data = n_manufac_year, 
  type = "column", 
  mapping = aes(
    x = manufacturer,
    y = pct, fill = year, 
    # Custom text to be displayed in tooltip
    custom_tooltip = paste0("Percentage: ", round(pct * 100), "% (total: ", n, ")")
  )
) %>% 
  ax_chart(stacked = TRUE) %>%
  ax_tooltip(
    y = list(
      # use custom text
      formatter = JS(
        "function(value, series) {return series.w.config.series[series.seriesIndex].data[series.dataPointIndex].custom_tooltip;}"
      )
    )
  )

But I'll love to implement something more user-friendly and robust across type of charts...

Victor

u909090 commented 3 years ago

Thanks Victor, it works great !

Implementing an easier formatter syntax for people who don't know JS would be useful for sure.

But also simply providing a link in the vignette to try to understand the JS syntax would already be very useful as well. When you go on this page, and click on the JS function under the 'Bar chart' section it redirects here. But to be honest I don't really understand the message.

u909090 commented 3 years ago

Hi Victor,

Related to this issue: is there a way to vertical-align up the series name in a tooltip generated from multiple custom tooltips? Example:

apex(
  data = n_manufac_year, 
  type = "column", 
  mapping = aes(
    x = manufacturer,
    y = pct, fill = year, 
    # Custom text to be displayed in tooltip
    custom_tooltip = paste0("Percentage= ", round(pct * 100), "%"),
    custom_tooltip_N = paste0("total=", n)
  )
) %>% 
  ax_chart(stacked = TRUE) %>%
  ax_tooltip(
    y = list(
      # use custom text
      formatter = JS(
        "function(value, series) {return(
             series.w.config.series[series.seriesIndex].data[series.dataPointIndex].custom_tooltip + '<br/>' + 
             series.w.config.series[series.seriesIndex].data[series.dataPointIndex].custom_tooltip_N)}"
      )
    )
  )

If not possible, could we remove the series name completely?