usert4jju7
usert4jju7

Reputation: 1813

Amcharts - Calculate & plot rate of change

I've got a set of values on a line chart that go as below

The data spans over years. The output in the picture above comes out f a SQL query from the database. The challenge I have is to represent both the actual number of page hits & also the rate of growth on the same graph.

I've plot the number of hits as a column graph with the number of hits being the Y-axis on left hand side. I've created a multiline chart & combination of line & column earlier. So, can create one for this too. However, is there a way amcharts can calculate the rate of change without me having to extract that as another field of the SQL query?

I'd like to see amcharts plot a line graph for the rate of change along a Y-axis on the right hand side say. Any other ideas of dealing with this is also much appreciated.

REMAINDER OF THE PUZZLE

In the above picture, the "# EVENT" & "EVENT # - GROWTH RATE" both show the same value. How could I get "EVENT # - GROWTH RATE" to actually show the % change (69% as per the picture attached) rather than the value?

The above output is from the firebug trace. As it shows, 2 graphs have same "value" plot on 2 different value axes one of which has percentage enabled.

Upvotes: 1

Views: 1179

Answers (1)

martynasma
martynasma

Reputation: 8595

You could create a separate graph and value axis for that. The value axis has a property recalculateToPercents which when set to true will recalculate the absolute values to a change in percents.

So you would have one regular graph like you do right now, and a separate graph/value axis duo to display the dynamics.

I think a working example might be better to illustrate this:

var chart = AmCharts.makeChart("chartdiv", {
  "type": "serial",
  "theme": "light",
  "dataDateFormat": "YYYY-MM-DD",
  "valueAxes": [{
    "id": "v1",
    "position": "left",
    "minimum": 0,
    "maximum": 100
  }, {
    "id": "v2",
    "gridAlpha": 0,
    "position": "left",
    "offset": 60,
    "recalculateToPercents": true
  }],
  "graphs": [{
    "id": "g1",
    "bullet": "round",
    "lineThickness": 2,
    "title": "Absolute values",
    "valueField": "value",
    "valueAxis": "v1"
  }, {
    "id": "g1",
    "bullet": "round",
    "lineThickness": 2,
    "title": "Change values",
    "valueField": "value",
    "valueAxis": "v2",
    "showBalloon": false
  }],
  "legend": {
    "valueText": ""
  },
  "chartCursor": {
    "valueLineEnabled": true,
    "valueLineBalloonEnabled": true,
    "cursorAlpha": 1,
    "cursorColor": "#258cbb",
    "limitToGraph": "g1",
    "valueLineAlpha": 0.2
  },
  "categoryField": "date",
  "categoryAxis": {
    "parseDates": true
  },
  "dataProvider": [ {
    "date": "2013-01-02",
    "value": 67
  }, {
    "date": "2013-01-03",
    "value": 64
  }, {
    "date": "2013-01-04",
    "value": 66
  }, {
    "date": "2013-01-05",
    "value": 60
  }, {
    "date": "2013-01-06",
    "value": 63
  }, {
    "date": "2013-01-07",
    "value": 61
  }, {
    "date": "2013-01-08",
    "value": 60
  }, {
    "date": "2013-01-09",
    "value": 65
  }, {
    "date": "2013-01-10",
    "value": 75
  }, {
    "date": "2013-01-11",
    "value": 77
  }, {
    "date": "2013-01-12",
    "value": 78
  }, {
    "date": "2013-01-13",
    "value": 70
  }, {
    "date": "2013-01-14",
    "value": 70
  }, {
    "date": "2013-01-15",
    "value": 73
  }, {
    "date": "2013-01-16",
    "value": 71
  }, {
    "date": "2013-01-17",
    "value": 74
  }, {
    "date": "2013-01-18",
    "value": 78
  }, {
    "date": "2013-01-19",
    "value": 85
  }, {
    "date": "2013-01-20",
    "value": 82
  }, {
    "date": "2013-01-21",
    "value": 83
  }, {
    "date": "2013-01-22",
    "value": 88
  }, {
    "date": "2013-01-23",
    "value": 85
  }, {
    "date": "2013-01-24",
    "value": 85
  }, {
    "date": "2013-01-25",
    "value": 80
  }, {
    "date": "2013-01-26",
    "value": 87
  }, {
    "date": "2013-01-27",
    "value": 84
  }, {
    "date": "2013-01-28",
    "value": 83
  }, {
    "date": "2013-01-29",
    "value": 84
  }, {
    "date": "2013-01-30",
    "value": 81
  }]
});
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv" style="width: 100%; height: 300px;"></div>

You'll notice that both graphs use the same valueField.


The above solution will calculate the change to the first value.

If you need the change to be calculated from any previous data point, you will need to pre-process the data.

We can use the AmCharts.addInitHandler() method to specify custom function which will be called before chart is initialized, so we can make some last-minute modifications and calculations to it.

The below solution will use it to look for a proprietary setting recalculate in graphs, and will automatically recalculate its absolute data values to change in percent.

Needles to say, this won't work if your data contains at least one zero value, because there's no way how to calculate a percent change from zero.

AmCharts.addInitHandler(function(chart) {
  
  // look for graphs that need to be recalculated
  var graphs = [];
  for(var i = 0; i < chart.graphs.length; i++) {
    var graph = chart.graphs[i];
    if (graph.recalculate === true) {
      graph.originalValueField = graph.valueField;
      graph.valueField = graph.valueField + "Change";
      graphs.push(graph);
    }
  }
  
  // calculate the data
  var prev = [];
  for(var i = 0; i < chart.dataProvider.length; i++) {
    var dp = chart.dataProvider[i];
 
    for(var g = 0; g < graphs.length; g++) {
      var graph = graphs[g];
            
      // ignore empty data points
      if(isNaN(dp[graph.originalValueField]))
        continue;
      
      // handle first data point
      if(prev[g] === undefined) {
        prev[g] = dp[graph.originalValueField];
      }
      
      // calculate the change
      var change = dp[graph.originalValueField] - prev[0];
      dp[graph.valueField] = Math.round( change / prev[0] * 10000) / 100;
      
      // assign previous value
      prev[g] = dp[graph.originalValueField];
        
    }
  }
  
  console.log(chart.dataProvider);
  
}, ["serial"]);

var chart = AmCharts.makeChart("chartdiv", {
  "type": "serial",
  "theme": "light",
  "dataDateFormat": "YYYY-MM-DD",
  "valueAxes": [{
    "id": "v1",
    "position": "left"
  }, {
    "id": "v2",
    "gridAlpha": 0,
    "position": "left",
    "offset": 60,
    "unit": "%"
  }],
  "graphs": [{
    "id": "g1",
    "bullet": "round",
    "lineThickness": 2,
    "title": "Absolute values",
    "valueField": "value",
    "valueAxis": "v1"
  }, {
    "id": "g2",
    "bullet": "round",
    "lineThickness": 2,
    "title": "Change values",
    "valueField": "value",
    "valueAxis": "v2",
    "recalculate": true,
    "balloonText": "[[value]]%"
  }],
  "legend": {
    "valueText": ""
  },
  "chartCursor": {
    "valueLineEnabled": true,
    "valueLineBalloonEnabled": true,
    "cursorAlpha": 1,
    "cursorColor": "#258cbb",
    "limitToGraph": "g1",
    "valueLineAlpha": 0.2
  },
  "categoryField": "date",
  "categoryAxis": {
    "parseDates": true
  },
  "dataProvider": [ {
    "date": "2013-01-02",
    "value": 67
  }, {
    "date": "2013-01-03",
    "value": 64
  }, {
    "date": "2013-01-04",
    "value": 66
  }, {
    "date": "2013-01-05",
    "value": 60
  }, {
    "date": "2013-01-06",
    "value": 63
  }, {
    "date": "2013-01-07",
    "value": 61
  }, {
    "date": "2013-01-08",
    "value": 60
  }, {
    "date": "2013-01-09",
    "value": 65
  }, {
    "date": "2013-01-10",
    "value": 75
  }, {
    "date": "2013-01-11",
    "value": 77
  }, {
    "date": "2013-01-12",
    "value": 78
  }, {
    "date": "2013-01-13",
    "value": 70
  }, {
    "date": "2013-01-14",
    "value": 70
  }, {
    "date": "2013-01-15",
    "value": 73
  }, {
    "date": "2013-01-16",
    "value": 71
  }, {
    "date": "2013-01-17",
    "value": 74
  }, {
    "date": "2013-01-18",
    "value": 78
  }, {
    "date": "2013-01-19",
    "value": 85
  }, {
    "date": "2013-01-20",
    "value": 82
  }, {
    "date": "2013-01-21",
    "value": 83
  }, {
    "date": "2013-01-22",
    "value": 88
  }, {
    "date": "2013-01-23",
    "value": 85
  }, {
    "date": "2013-01-24",
    "value": 85
  }, {
    "date": "2013-01-25",
    "value": 80
  }, {
    "date": "2013-01-26",
    "value": 87
  }, {
    "date": "2013-01-27",
    "value": 84
  }, {
    "date": "2013-01-28",
    "value": 83
  }, {
    "date": "2013-01-29",
    "value": 84
  }, {
    "date": "2013-01-30",
    "value": 81
  }]
});
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv" style="width: 100%; height: 300px;"></div>

Upvotes: 3

Related Questions