Sometimes you will end up with an XY chart that has non-unique categories in its data. This tutorial will explain how to deal with such situation.
We’re going to start off with a very basic XY chart that has a category axis, and some matching categories in its data:
If we run a chart like this, the data points with matching categories will overlap:
Run * --------------------------------------------------------
* This demo was created using amCharts V4 preview release.
* V4 is the latest installement in amCharts data viz
* library family, to be released in the first half of
* For more information and documentation visit:
* https://www.amcharts.com/docs/v4/
* --------------------------------------------------------
am4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . dataFields . category = " category " ;
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . renderer . minGridDistance = 30 ;
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . ColumnSeries ());
series . dataFields . valueY = " value " ;
series . dataFields . categoryX = " category " ;
series . columns . template . fillOpacity = 0.5 ;
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Repeating categories (1) repeating-categories-1
That’s obviously not what we were looking for.
Let’s see how we can rectify the situation.
On of the most obvious solution is to make those categories unique.
For example, we could add some suffix to the categories:
That would surely fix the issue. However, we’d end up with additional numbers on our category labels, that are useless if not outright misleading to user viewing the chart:
Run * --------------------------------------------------------
* This demo was created using amCharts V4 preview release.
* V4 is the latest installement in amCharts data viz
* library family, to be released in the first half of
* For more information and documentation visit:
* https://www.amcharts.com/docs/v4/
* --------------------------------------------------------
am4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . dataFields . category = " category " ;
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . renderer . minGridDistance = 30 ;
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . ColumnSeries ());
series . dataFields . valueY = " value " ;
series . dataFields . categoryX = " category " ;
series . columns . template . fillOpacity = 0.5 ;
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Repeating categories (2) repeating-categories-2
Luckily, amCharts 4 has a powerful feature - Adapters - that allow using custom code to dynamically change just about anything.
We can surely use those to strip off our excess suffix from the labels:
categoryAxis.renderer.labels.template.adapter.add("textOutput", function(text) {
return text.replace(/ \(.*/, "");
categoryAxis.renderer.labels.template.adapter.add("textOutput", function(text) {
return text.replace(/ \(.*/, "");
"textOutput": function(text) {
return text.replace(/ \(.*/, "");
An Adapter is basically a mean to run some value via custom function, giving a chance to modify it using custom code, before the value is displayed or used.
In the code above, we’re using a "textOutput" adapter on axis’ label template to replace suffix using a Regular Expression.
Let’s see how it turned out:
Run * --------------------------------------------------------
* This demo was created using amCharts V4 preview release.
* V4 is the latest installement in amCharts data viz
* library family, to be released in the first half of
* For more information and documentation visit:
* https://www.amcharts.com/docs/v4/
* --------------------------------------------------------
am4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . dataFields . category = " category " ;
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . renderer . minGridDistance = 30 ;
categoryAxis . renderer . labels . template . adapter . add ( " textOutput " , function ( text ) {
return text . replace ( / \( . * / , "" );
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . ColumnSeries ());
series . dataFields . valueY = " value " ;
series . dataFields . categoryX = " category " ;
series . columns . template . fillOpacity = 0.5 ;
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Repeating categories (3) repeating-categories-3
Perfect!
If we don’t want (or can’t) change our source data, we may employ chart’s beforedatavalidated event to add suffixes to category names automatically, before chart parses the data:
chart . events . on ( " beforedatavalidated " , function () {
for ( let i = 0 ; i < chart . data . length ; i ++ ) {
chart . data [i] . category += " ( " + i + " ) " ;
chart . events . on ( " beforedatavalidated " , function () {
for ( var i = 0 ; i < chart . data . length ; i ++ ) {
chart . data [ i ] . category += " ( " + i + " ) " ;
"beforedatavalidated" : function(ev) {
for(var i = 0; i < chart.data.length; i++) {
chart.data[i].category += " (" + i + ")" ;
Run * --------------------------------------------------------
* This demo was created using amCharts 4.
* For more information and documentation visit:
* https://www.amcharts.com/docs/v4/
* --------------------------------------------------------
am4core . useTheme ( am4themes_animated );
var chart = am4core . create ( " chartdiv " , am4charts . XYChart );
chart . events . on ( " beforedatavalidated " , function () {
for ( var i = 0 ; i < chart . data . length ; i ++ ) {
chart . data [ i ] . category += " ( " + i + " ) " ;
var categoryAxis = chart . xAxes . push ( new am4charts . CategoryAxis ());
categoryAxis . dataFields . category = " category " ;
categoryAxis . renderer . grid . template . location = 0 ;
categoryAxis . renderer . minGridDistance = 30 ;
categoryAxis . renderer . labels . template . adapter . add ( " textOutput " , function ( text ) {
return text . replace ( / \( . * / , "" );
var valueAxis = chart . yAxes . push ( new am4charts . ValueAxis ());
var series = chart . series . push ( new am4charts . ColumnSeries ());
series . dataFields . valueY = " value " ;
series . dataFields . categoryX = " category " ;
series . columns . template . fillOpacity = 0.5 ;
< div id = " chartdiv " ></ div >
-apple-system , BlinkMacSystemFont, " Segoe UI " , Roboto, Helvetica , Arial , sans-serif ,
" Apple Color Emoji " , " Segoe UI Emoji " , " Segoe UI Symbol " ;
Repeating categories (automated) repeating-categories-automated