0

I am needing to display stackLabels on the stacked bar chart as both a total of the stack and a percent of the total. This question gives a version of the answer I am looking for, but the data var they declare at the beginning of the code is hardcoded data, whereas I will need it to be dynamic. Additionally, I have several series I am dealing with that all need to be summed together (example below just uses two). I think the main thing I am missing is how to reference associated data from JS code to sum over it? I am very unfamiliar with JS.

For the example code and plot below, I want the stackLabels to say '30(30%)' for a, '20(20%)' for b, '50(50%)' for a. (If it was a different data set of 10, 20, and 30 it would be '10(17%)' for a, '20(33%)' for b, '30(50%)' for c since the total across everything would be 60.)

library(highcharter)
library(dplyr)

df <- data.frame(z = c(20,4,6,8,25),
                y = c(3,3,2,4,25),
                x = c('a', 'a', 'b', 'b', 'c'))
df <- df %>% group_by(x) %>% summarize(y = sum(y), z = sum(z), total = sum(y,z))
df

highchart() %>% 
  hc_chart(type = 'column') %>% 
  hc_plotOptions(column = list(stacking = 'normal')) %>% 
  hc_xAxis(categories = as.factor(unique(df$x))) %>% 
  hc_add_series(df$y, name = 'y', stack = 'stack') %>% 
  hc_add_series(df$z, name = 'z', stack = 'stack') %>% 
  hc_yAxis(stackLabels = list(enabled = TRUE)) %>% 
  hc_tooltip(shared = TRUE)

Test Plot

Based on the linked question above, I am thinking I need to alter the code to add a loop sum, but am not sure how to finish it.

highchart() %>% 
  hc_chart(type = 'column') %>% 
  hc_plotOptions(column = list(stacking = 'normal')) %>% 
  hc_xAxis(categories = as.factor(unique(df$x))) %>% 
  hc_add_series(df$y, name = 'y', stack = 'stack') %>% 
  hc_add_series(df$z, name = 'z', stack = 'stack') %>% 
  hc_yAxis(stackLabels = list(enabled = TRUE, 
                              formatter = JS("function() {var data = *reference to the data*;
                                                          var dataSum = 0;
                                                          for (var i=0;i < data.length;i++) {
                                                              dataSum += data[i]
                                                          }
                                                          var pcnt = (this.y / dataSum) * 100;
                                                          return Highcharts.numberFormat(pcnt) + '%';
                                                      }"))) %>% 
  hc_tooltip(shared = TRUE)

Please advise. Still new to stack overflow so let me know if I missed anything.

1 Answers1

0

Edit

Revised answer as OP appears to want each stack label to show the subtotal as a proportion of all stacks as well as the N.

I added some more random data to the set. The main thing is to include the total across every series. Then you can use that number within formatter to divide the stack totals.

df <- data.frame(
  z = c(20,4,26,8,25,10),
  y = c(3,10,2,34,25,41),
  x = c('a','a','b','b','c','c')
)

df <- df %>% 
  group_by(x) %>% 
  summarize(y = sum(y), z = sum(z), sub_total = sum(y,z)) %>%
  mutate(total = sum(sub_total))

highchart() %>% 
  hc_chart(type = 'column') %>% 
  hc_plotOptions(column = list(stacking = 'normal')) %>% 
  hc_xAxis(categories = as.factor(unique(df$x))) %>% 
  hc_add_series(df$y, name = 'y', stack = 'stack') %>% 
  hc_add_series(df$z, name = 'z', stack = 'stack') %>% 
  hc_yAxis(stackLabels = list(enabled = TRUE,
    formatter = JS(paste0("function() {
      var prop = this.total / ", unique(df$total) ," * 100
      prop = Highcharts.numberFormat(prop)
      return this.total + ' (' + prop + '%)';
    }")))) %>% 
  hc_tooltip(shared = TRUE)

enter image description here


Prev Answer

I'm not quite sure what you're asking.

I am needing to display stackLabels on the stacked bar chart as both a total of the stack and a percent of the total.

It would seem to me that "% of the total" should always equal 100% if you're taking the sum of all series, e.g. total/total = 1. However, maybe I'm missing something here.

In any case, the following code will replicate the stack labels you're looking for. Where this.total represents the total of each stacked item.

highchart() %>% 
  hc_chart(type = 'column') %>% 
  hc_plotOptions(column = list(stacking = 'normal')) %>% 
  hc_xAxis(categories = as.factor(unique(df$x))) %>% 
  hc_add_series(df$y, name = 'y', stack = 'stack') %>% 
  hc_add_series(df$z, name = 'z', stack = 'stack') %>% 
  hc_yAxis(stackLabels = list(enabled = TRUE,
    formatter = JS("function() {
      return this.total + '(' + this.total + '%)'             
    }"))) %>% 
  hc_tooltip(shared = TRUE)

example

Jamie
  • 1,793
  • 6
  • 16
  • Thank you for your response. I realized I had not put together the correct data set to display what I was wanting (I put 40 instead of 50 for c so that the total didn't add up to 100). I have made edits to reflect it correctly. The code you provided just makes same number a percent, when actually I need it as a percent of the total - see my edits for an example. If the numbers stayed as before, the total would be 30+20+40 = 90, so I would want to display 30(33%), 20(22%), 40(44%). Hope that clarifies, sorry for the confusing post. – passer_days May 09 '23 at 20:01
  • @passer_days - I updated my answer. Let me know if that is more inline with what you're looking for. – Jamie May 09 '23 at 23:37