Handling repeating categories on Category Axis
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.
Base chart
Section titled “Base chart”We’re going to start off with a very basic XY chart that has a category axis, and some matching categories in its data:
[{ "category": "1st", "value": 450}, { "category": "2nd", "value": 1200}, { "category": "3rd", "value": 1850}, { "category": "1st", "value": 1251}, { "category": "2nd", "value": 599}, { "category": "3rd", "value": 1033}]If we run a chart like this, the data points with matching categories will overlap:
That’s obviously not what we were looking for.
Let’s see how we can rectify the situation.
Adding category suffix
Section titled “Adding category suffix”On of the most obvious solution is to make those categories unique.
For example, we could add some suffix to the categories:
[{ "category": "1st (1)", "value": 450}, { "category": "2nd (2)", "value": 1200}, { "category": "3rd (3)", "value": 1850}, { "category": "1st (4)", "value": 1251}, { "category": "2nd (5)", "value": 599}, { "category": "3rd (6)", "value": 1033}]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:
Stripping suffix
Section titled “Stripping suffix”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(/ \(.*/, "");});{ // ... "xAxes": { "type": "CategoryAxis", // ... "renderer": { // ... "adapter": { "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:
Perfect!
Automated solution
Section titled “Automated solution”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 + ")"; }});{ // ... events: { "beforedatavalidated": function(ev) { var chart = ev.target; for(var i = 0; i < chart.data.length; i++) { chart.data[i].category += " (" + i + ")"; } } }}