使用 D3 绘制趋势线 - 实际值和预测值

Plotting a trendline with D3 - Actual & Forecast

我有一个多系列折线图,每个系列都有一条趋势线。我的数据格式如下,前半部分是实际数据,后半部分是预测(预测)数据。所以在前 32 周,我有真实数据,然后这些字段变为 0。然后预测字段有数字,实际部分为 0。您可以通过查看数据来了解这一点。我用 if 语句处理这个问题。

两个系列的线都是准确的。

我的问题是预测的趋势线是错误的,我没能弄明白,因为它对实际部分是正确的。

如果您在此处将配置参数从 "forecast" 更改为 "actual",您可以看到图表中的差异:

"config": {
    "measure": "DNGP",
    "time": "forecast"
  }

我用网上找到的这个方法给图表添加趋势线:

var xSeries;
  var ySeries;
  var leastSquaresCoeff1;
  var x1;
  var y1;
  var x2;
  var y2;
  var trendData = []
  var trendline;
  var leastSquaresCoeff;

  // get the x and y values for least squares
  xSeries = d3.range(d3.min(actualData, function(d) {
    return d.items[columns.indexOf("Week")];
  }), d3.max(actualData, function(d) {
    return d.items[columns.indexOf("Week")];
  }) + 1);
  ySeries = actualData.map(function(d) {
    return parseFloat(d.items[columns.indexOf("Measure")])
  });

  leastSquaresCoeff = leastSquares(xSeries, ySeries);

  // apply the reults of the least squares regression
  x1 = actualData[0].items[columns.indexOf("Week")];
  y1 = leastSquaresCoeff[0] + leastSquaresCoeff[1];
  x2 = actualData[actualData.length - 1].items[columns.indexOf("Week")];
  y2 = leastSquaresCoeff[0] * xSeries.length + leastSquaresCoeff[1];
  trendData = [
    [x1, y1, x2, y2]
  ];

  trendline = svg.selectAll(".trendline")
    .data(trendData).enter()
    .append("line")
    .attr("class", "trendline")
    .style("stroke-dasharray", ("3, 3"))
    .attr("x1", function(d) {
      return x(d[0]);
    })
    .attr("y1", function(d) {
      return y(d[1]);
    })
    .attr("x2", function(d) {
      return x(d[2]);
    })
    .attr("y2", function(d) {
      return y(d[3]);
    })
    .attr("stroke", "#319455")
    .attr("stroke-width", 1);

你可以在这里看到我的fiddle(目前设置为预测):http://jsfiddle.net/euLgczjf/4/

我仍然不知道为什么这不起作用。但是我使用外部库找到了不同的解决方案。

我的解决方案基于此示例:http://bl.ocks.org/tmcw/3931800/972696d92e86c4f541ec0c89b5657771b40e99fa

这段代码没有绘制回归线:

var regLine = d3.line()
    .x(function(d) { 
        return x(d.Week); 
    })
    .y(function(d) { 
        return y(d.Measure); 
    });

  // Derive a linear regression
  var regression = ss.linearRegression(actualData.map(function(d) {
    return [+d.items[columns.indexOf("Week")], d.items[columns.indexOf("Measure")]];
  }));

  var lin = ss.linearRegressionLine(regression);

  // Create a line based on the beginning and endpoints of the range
  var lindata = x.domain().map(function(x) {
    return {
      Week: x,
      Measure: lin(+x)
    };
  });

  svg.append("path")
      .datum(lindata)
      .attr("class", "reg")
        .style("stroke-dasharray", ("3, 3"))
        .attr("stroke", "#319455")
        .attr("stroke-width", 1)
      .attr("d", regLine);

完成图表:http://jsfiddle.net/euLgczjf/5/