3

I have scatter graph which contains a lot of data, too much to display to a user. I would like to add a line of best fit or 'trendline' to the graph to show the trend and make the scatter plots invisible. My data is stored in an external JSON file in the format:

{
    "X" : [1,2,3,4,5,6,7,8,9...],
    "Y" : [1,2,3,4,5,6,7,8,9...]
}

And I am displaying my data using this code:

function addData(data){
  console.log("Adding data");
  var gradeMaxLength = 0; 

  for( var i = 0; i < data.length; i++ ){
    if( gradeMaxLength < data[i].grade.length ){
      gradeMaxLength = data[i].grade.length;
    }
  }

  // addding datSeries
  for( var j = 0; j < gradeMaxLength; j++ ){
    chart.options.data.push({
      type:"scatter",
      dataPoints:[]
    });
  }

  // adding dataPoints
  for( var k = 0; k < data.length; k++ ){
    for( var l = 0; l < gradeMaxLength; l++ ){
      chart.options.data[l].dataPoints.push({
        x: data[k].present[l],
        y: data[k].grade[l]
      }
    );
  }
}
chart.render();
}

Is there a way I can add a line of best fit to my graph, of which I have included a photo of below?

Graph

  • 1
    If it isn't built into CanvasJS, you could just 1) calculate the line (fairly easy, just a few lines of code) then 2) plot the line (which *will* be built into CanvasJS). – John Coleman Oct 31 '19 at 12:15
  • 1
    @JohnColeman I figured I would have to do this but I was just wondering if anyone had found a way to do it in CanvasJS's library –  Oct 31 '19 at 12:32
  • 2
    A quick check of the library documentation doesn't turn up anything. The fact that they refer to vertical and horizontal lines as "Trend Lines" isn't very encouraging. It is a graphics library, not a data analysis library. – John Coleman Oct 31 '19 at 12:38

1 Answers1

2

For canvasJS you could use this piece of code. I use it for myself for a while now but it works perfectly!

Add this after your chart.render();

    calculateTrendLine(chart);
    function calculateTrendLine(chart){
        var a, b, c, d, e, slope, yIntercept;
        var xSum = 0, ySum = 0, xySum = 0, xSquare = 0, dpsLength = chart.data[0].dataPoints.length;
        for(var i = 0; i < dpsLength; i++)
            xySum += (chart.data[0].dataPoints[i].x * chart.data[0].dataPoints[i].y)
        a = xySum * dpsLength;

        for(var i = 0; i < dpsLength; i++){
            xSum += chart.data[0].dataPoints[i].x;
            ySum += chart.data[0].dataPoints[i].y;
        }
        b = xSum * ySum;

        for(var i = 0; i < dpsLength; i++)
            xSquare += Math.pow(chart.data[0].dataPoints[i].x, 2);
        c = dpsLength * xSquare;

        d = Math.pow(xSum, 2);
        slope = (a-b)/(c-d);
        e = slope * xSum;
        yIntercept = (ySum - e) / dpsLength;

        var startPoint = getTrendLinePoint(chart.data[0].dataPoints[0].x, slope, yIntercept);
        var endPoint = getTrendLinePoint(chart.data[0].dataPoints[dpsLength-1].x, slope, yIntercept);

        chart.addTo("data",{
            type: "line", //Line series showing trend
            markerSize: 0,
            dataPoints: [startPoint, endPoint]
        });
    }

    function getTrendLinePoint(x, slope, intercept){
        return {x: x, y: ((slope * x) + intercept)};
    }
Fabian Bron
  • 106
  • 5
  • I have added this code to my js file but it is not rendering anything. Do you think you could provide me with a jsfiddle to show me it in action? https://jsfiddle.net/ –  Oct 31 '19 at 15:00
  • 1
    Hey Jolene, That's odd... I added my template for graphs like this here https://jsfiddle.net/7atep56c/3/ it is pretty easy to integrate your addData into this script. Hope you can integrate it, if not let me know! – Fabian Bron Oct 31 '19 at 16:46
  • I got it working! The format of my JSON data was the problem. Thank you! –  Nov 04 '19 at 10:04