12

I have a simple 1-series bar chart where each bar has a nominal value. I can plot this fine with the data labels and axis representing the value for each bar but I'd like to have the data label and axis show the percentage of the total of the series while the nominal value is shown in a tooltip on hover (thus I don't want to convert the data to percentages prior to plotting).

Here is an image showing what I'm after and where I am now:

fiddle

enter image description here

Here's what I currently have for axis labels as the formatter function:

plotOptions: {
            bar: {
                dataLabels: {
                    enabled: true,
                    formatter: function(){
                        return Highcharts.numberFormat(this.y,0);
                    }
                }
            }
        }

Is there some formatter function variable I can use to achieve this? I know it is easily done on a pie chart but I feel bar charts represent data much better.

EDIT: To put it simply, how do I get the sum of all the series' points? Once I have this it is straightforward to get the percentage:

return Highcharts.numberFormat(100 * this.y / this.y.total,0) + "%";

where this.y.total is the sum of the series.

JayPeerachai
  • 3,499
  • 3
  • 14
  • 29
harryg
  • 23,311
  • 45
  • 125
  • 198

4 Answers4

28

You'll have to loop through the data and get the total, and then use the datalabel formatter function to get the percent.

Example here:

http://jsfiddle.net/JVNjs/319/

formatter:function() {
  var pcnt = (this.y / dataSum) * 100;
  return Highcharts.numberFormat(pcnt) + '%';
}

edit::

updated example with axis labels:

http://jsfiddle.net/JVNjs/320/

[[EDIT for comments

If you are trying to plot the percent values of multiple series, there are a variety of fundamental problems that arise.

If you are calculating the % of two different data series, and displaying the % value even though you've plotted the raw value, your chart will be misleading and confusing in most cases.

Plotting the data as the percent values directly is the best way to go in that case, and you can add the raw data value as an extra property in the point object if you want to display it in a tool tip or elsewhere ( ie http://jsfiddle.net/JVNjs/735/ )

If you insist on using the original method on two different series, then you can just create two different variables to calculate against, and check the series name in the formatter to determine which data sum to calculate against.

jlbriggs
  • 17,612
  • 4
  • 35
  • 56
  • this will work for only one series. if i have multiple series then ? – TechnoCrat Mar 02 '15 at 18:28
  • If you have multiple series you want to display as percents, what you should really be doing is plotting the percent values directly. If you then want to display the raw values in a tooltip, you can send that data is an optional property in the data point object. – jlbriggs Mar 02 '15 at 19:32
5

@jlbriggs had a great answer and lead me onto the path of creating this formatter function. This function always checks the current values in the data. If the data is updated programmatically at a later time, the percentages will reflect the newly updated data. No dataSum or loop is necessary as the .map().reduce() takes care of that for you.

dataLabels: {
  enabled: true,
  formatter: function() {
    var pcnt = (this.y / this.series.data.map(p => p.y).reduce((a, b) => a + b, 0)) * 100;
    return Highcharts.numberFormat(pcnt) + '%';
  }
}
strikemike2k
  • 151
  • 1
  • 5
-1

try this.percentage

It's pretty well documented in the highcharts API as well.

http://api.highcharts.com/highcharts#plotOptions.series.dataLabels.formatter

EDIT

Since you'd need it for non-stacked series, you'd need to get the total before generating the graph... The function below adds up your values into one variable which you can use in your formatter function later.

function arrayTotal(arr)
{
  var total = 0;
  for (var i = 0, value; value = arr[i]; i++)
  {
    total += value;
  }
  return total;
}
Joris Kroos
  • 431
  • 3
  • 17
  • Unfortunately that doesn't work. As it says in the documentation `this.percentage` just gives the percentage of a slice of a stacked series only. My series is not stacked, it is just one simple series. – harryg May 30 '13 at 13:45
  • Then make a custom function that outputs the total before setting it into highcharts itself. A "for" loop, increasing a variable by "y" each time would do the trick. – Joris Kroos May 30 '13 at 13:49
-1

Highchart library is very enrich with build in functions. if you would like to just for the number on chart up to certain number. you can give a try for below function.

import {numberFormat} from 'hicghart';

then you can achieve the below way formating

numberFormat(this.y,decimalPlaceToFormat)
Sachin Mishra
  • 1,125
  • 1
  • 16
  • 17