使用 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);
我有一个多系列折线图,每个系列都有一条趋势线。我的数据格式如下,前半部分是实际数据,后半部分是预测(预测)数据。所以在前 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);