使用D3绘制趋势线问题:实际与预测数据趋势线异常
Hey there, I spotted the issue causing your forecast trendline to draw incorrectly—it’s all in how you’re calculating the y-values for the trendline endpoints! Let’s break this down and fix it.
The Root Problem
In your code, you’re calculating y1 and y2 using logic that only works by coincidence for your actual data:
y1 = leastSquaresCoeff[0] + leastSquaresCoeff[1]; // Wrong! Should use x1 y2 = leastSquaresCoeff[0] * xSeries.length + leastSquaresCoeff[1]; // Wrong! Should use x2
For your actual data, x1 happens to be 1, so m*1 + b equals m + b—that’s why it works. And xSeries.length matches x2 (32), so m*32 + b is correct. But for forecast data, x1 starts at 33 and x2 is 64, while xSeries.length stays at 32—this misalignment breaks the trendline calculation entirely.
The Fix
You need to plug the actual x1 and x2 values directly into your least squares regression equation (y = mx + b, where leastSquaresCoeff[0] is the slope m and leastSquaresCoeff[1] is the intercept b). Here’s the corrected code section:
// 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 results of the least squares regression (CORRECTED!) x1 = actualData[0].items[columns.indexOf("Week")]; y1 = leastSquaresCoeff[0] * x1 + leastSquaresCoeff[1]; // Use x1 in the regression formula x2 = actualData[actualData.length - 1].items[columns.indexOf("Week")]; y2 = leastSquaresCoeff[0] * x2 + leastSquaresCoeff[1]; // Use x2 in the regression formula 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);
Why This Works
By using the actual week values (x1 and x2) in the regression equation, you ensure the trendline endpoints are calculated correctly regardless of whether you’re working with actual or forecast data. Now when you toggle the time config parameter between actual and forecast, both trendlines will align perfectly with their respective datasets.
内容的提问来源于stack exchange,提问作者CStreet

