amcharts / amcharts4

The most advanced amCharts charting library for JavaScript and TypeScript apps.
https://www.amcharts.com/
1.16k stars 321 forks source link

Regression equation #3301

Open tlebreton opened 3 years ago

tlebreton commented 3 years ago

Hi

I got a question about the regression plugin.

With a very simple graph i don't understand the equation result.

<head>
  <script src="https://www.amcharts.com/lib/4/core.js"></script>
  <script src="https://www.amcharts.com/lib/4/charts.js"></script>
  <script src="https://www.amcharts.com/lib/4/plugins/regression.js"></script>

  <title>Bug Example</title>
  </head>

  <body>

  <div id="plot" style="width: 90%; height: 400px;" ></div>

  <script>
      let chart = am4core.create("plot", am4charts.XYChart);

      chart.data = [{x:20, y:20}, {x:40, y:40}, {x:80, y:80}, {x:100, y:100}];

      chart.xAxes.push(new am4charts.ValueAxis());
      chart.yAxes.push(new am4charts.ValueAxis());
      series = chart.series.push(new am4charts.LineSeries());

      series.dataFields.valueY = "y";
      series.dataFields.valueX = "x";

      const bullet = series.bullets.push(new am4charts.CircleBullet());
      bullet.circle.strokeWidth = 2;
      bullet.circle.radius = 4;

      series.stroke = null;
      let regseries = chart.series.push(new am4charts.LineSeries());
      regseries.dataFields.valueY = "y";
      regseries.dataFields.valueX = "x";
      regseries.strokeWidth = 2;
      regseries.name = "Linear Regression";

      let reg = regseries.plugins.push(new am4plugins_regression.Regression());
      reg.simplify = true;
      var label = chart.tooltipContainer.createChild(am4core.Label);
      label.x = am4core.percent(100);
      label.marginRight = 50;
      label.y = 30;
      label.align = "right"
      label.toFront();

      reg.events.on("processed", function(ev) {
        label.text = "[bold]equation:[/] " + ev.target.result.string.replace(/\^2/, "²") + "\n[bold]R²:[/] " + ev.target.result.r2;
      });

  </script>
  </body>

The result of the equation is strange for me. I expect to get this result :

In debugging the result i found that the point are strange :

[
 [0, 18],
 [1, 46],
 [2, 74],
 [3, 102]
]

It appears to me that the x value is ignored and replace by the index of the array which doesn't make sense to me.

In the docs there is this sentence :

On scatter charts - where you have value axes on both X and Y - data points can come in any order. This might produce an odd-looking trend line

Do you handle correctly a regression with two value axis or not?

martynasma commented 3 years ago

Do you handle correctly a regression with two value axis or not?

No, I'm afraid.

It will work only on regularly spaced data items.

We'll need to update the docs. Sorry for the confusion.

tlebreton commented 3 years ago

Hi

Ok it's not a real problem :)

Do you think that in the future you will implement this kind of regression ? I think it will be more usefull that the "regression" that is allready implemented

Thanks for the answer.

martynasma commented 3 years ago

There's no plan for that, but who knows :)

I'm gonna leave this open for now.

ChazUK commented 3 years ago

I've also been looking for the ability to add trend lines to a scatter / bubble chart with multiple series

CiaccoDavide commented 2 years ago

If anyone (maybe @ChazUK) is interested in a simple solution I used ml-regression-simple-linear to calculate the linear regression of my scatter charts:

import SimpleLinearRegression from 'ml-regression-simple-linear';

// ...

if (graphData.length > 1) {
    const x = graphData.map(({ x }) => x);
    const y = graphData.map(({ y }) => y);

    const regression = new SimpleLinearRegression(x, y);

    var fixedLinearRegression = chart.series.push(new am4charts.LineSeries());
    fixedLinearRegression.data = [
        { x: x[0], y: regression.predict(x[0]) },
        { x: x[x.length - 1], y: regression.predict(x[x.length - 1]) },
    ];
    fixedLinearRegression.dataFields.valueX = "x";
    fixedLinearRegression.dataFields.valueY = "y";
    fixedLinearRegression.strokeWidth = 2;
    fixedLinearRegression.stroke = am4core.color("#ff6860");
    fixedLinearRegression.name = "Linear Regression";
}

before:

Screenshot 2021-10-19 at 16 01 29

after:

Screenshot 2021-10-19 at 16 21 38