Created
January 16, 2014 17:50
-
-
Save benvandyke/8459843 to your computer and use it in GitHub Desktop.
Plotting a trendline with D3.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<title>Plotting a Trendline with D3.js</title> | |
<style> | |
.line { | |
stroke: blue; | |
fill:none; | |
stroke-width: 3; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-size: 10px; | |
font-family: sans-serif; | |
} | |
.text-label { | |
font-size: 10px; | |
font-family: sans-serif; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var height = 300; | |
var width = 600; | |
var margin = {top: 20, right:20, bottom: 50, left: 20}; | |
// formatters for axis and labels | |
var currencyFormat = d3.format("$0.2f"); | |
var decimalFormat = d3.format("0.2f"); | |
var svg = d3.select("body") | |
.append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
svg.append("g") | |
.attr("class", "y axis"); | |
svg.append("g") | |
.attr("class", "x axis"); | |
var xScale = d3.scale.ordinal() | |
.rangeRoundBands([margin.left, width], .1); | |
var yScale = d3.scale.linear() | |
.range([height, 0]); | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.orient("bottom"); | |
var yAxis = d3.svg.axis() | |
.scale(yScale) | |
.orient("left"); | |
d3.csv("usd_euro.csv", function(data) { | |
// extract the x labels for the axis and scale domain | |
var xLabels = data.map(function (d) { return d['yearmonth']; }) | |
xScale.domain(xLabels); | |
yScale.domain([0, Math.round(d3.max(data, function(d) { return parseFloat(d['rate']); }))]); | |
var line = d3.svg.line() | |
.x(function(d) { return xScale(d['yearmonth']); }) | |
.y(function(d) { return yScale(d['rate']); }); | |
svg.append("path") | |
.datum(data) | |
.attr("class","line") | |
.attr("d", line); | |
svg.select(".x.axis") | |
.attr("transform", "translate(0," + (height) + ")") | |
.call(xAxis.tickValues(xLabels.filter(function(d, i) { | |
if (i % 12 == 0) | |
return d; | |
}))) | |
.selectAll("text") | |
.style("text-anchor","end") | |
.attr("transform", function(d) { | |
return "rotate(-45)"; | |
}); | |
svg.select(".y.axis") | |
.attr("transform", "translate(" + (margin.left) + ",0)") | |
.call(yAxis.tickFormat(currencyFormat)); | |
// chart title | |
svg.append("text") | |
.attr("x", (width + (margin.left + margin.right) )/ 2) | |
.attr("y", 0 + margin.top) | |
.attr("text-anchor", "middle") | |
.style("font-size", "16px") | |
.style("font-family", "sans-serif") | |
.text("USD/EURO Exhange Rate"); | |
// x axis label | |
svg.append("text") | |
.attr("x", (width + (margin.left + margin.right) )/ 2) | |
.attr("y", height + margin.bottom) | |
.attr("class", "text-label") | |
.attr("text-anchor", "middle") | |
.text("Year-Month"); | |
// get the x and y values for least squares | |
var xSeries = d3.range(1, xLabels.length + 1); | |
var ySeries = data.map(function(d) { return parseFloat(d['rate']); }); | |
var leastSquaresCoeff = leastSquares(xSeries, ySeries); | |
// apply the reults of the least squares regression | |
var x1 = xLabels[0]; | |
var y1 = leastSquaresCoeff[0] + leastSquaresCoeff[1]; | |
var x2 = xLabels[xLabels.length - 1]; | |
var y2 = leastSquaresCoeff[0] * xSeries.length + leastSquaresCoeff[1]; | |
var trendData = [[x1,y1,x2,y2]]; | |
var trendline = svg.selectAll(".trendline") | |
.data(trendData); | |
trendline.enter() | |
.append("line") | |
.attr("class", "trendline") | |
.attr("x1", function(d) { return xScale(d[0]); }) | |
.attr("y1", function(d) { return yScale(d[1]); }) | |
.attr("x2", function(d) { return xScale(d[2]); }) | |
.attr("y2", function(d) { return yScale(d[3]); }) | |
.attr("stroke", "black") | |
.attr("stroke-width", 1); | |
// display equation on the chart | |
svg.append("text") | |
.text("eq: " + decimalFormat(leastSquaresCoeff[0]) + "x + " + | |
decimalFormat(leastSquaresCoeff[1])) | |
.attr("class", "text-label") | |
.attr("x", function(d) {return xScale(x2) - 60;}) | |
.attr("y", function(d) {return yScale(y2) - 30;}); | |
// display r-square on the chart | |
svg.append("text") | |
.text("r-sq: " + decimalFormat(leastSquaresCoeff[2])) | |
.attr("class", "text-label") | |
.attr("x", function(d) {return xScale(x2) - 60;}) | |
.attr("y", function(d) {return yScale(y2) - 10;}); | |
}); | |
// returns slope, intercept and r-square of the line | |
function leastSquares(xSeries, ySeries) { | |
var reduceSumFunc = function(prev, cur) { return prev + cur; }; | |
var xBar = xSeries.reduce(reduceSumFunc) * 1.0 / xSeries.length; | |
var yBar = ySeries.reduce(reduceSumFunc) * 1.0 / ySeries.length; | |
var ssXX = xSeries.map(function(d) { return Math.pow(d - xBar, 2); }) | |
.reduce(reduceSumFunc); | |
var ssYY = ySeries.map(function(d) { return Math.pow(d - yBar, 2); }) | |
.reduce(reduceSumFunc); | |
var ssXY = xSeries.map(function(d, i) { return (d - xBar) * (ySeries[i] - yBar); }) | |
.reduce(reduceSumFunc); | |
var slope = ssXY / ssXX; | |
var intercept = yBar - (xBar * slope); | |
var rSquare = Math.pow(ssXY, 2) / (ssXX * ssYY); | |
return [slope, intercept, rSquare]; | |
} | |
</script> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
yearmonth | rate | |
---|---|---|
1999-01 | 1.1591 | |
1999-02 | 1.1203 | |
1999-03 | 1.0886 | |
1999-04 | 1.0701 | |
1999-05 | 1.063 | |
1999-06 | 1.0377 | |
1999-07 | 1.037 | |
1999-08 | 1.0605 | |
1999-09 | 1.0497 | |
1999-10 | 1.0706 | |
1999-11 | 1.0328 | |
1999-12 | 1.011 | |
2000-01 | 1.0131 | |
2000-02 | 0.9834 | |
2000-03 | 0.9643 | |
2000-04 | 0.9449 | |
2000-05 | 0.9059 | |
2000-06 | 0.9505 | |
2000-07 | 0.9386 | |
2000-08 | 0.9045 | |
2000-09 | 0.8695 | |
2000-10 | 0.8525 | |
2000-11 | 0.8552 | |
2000-12 | 0.8983 | |
2001-01 | 0.9376 | |
2001-02 | 0.9205 | |
2001-03 | 0.9083 | |
2001-04 | 0.8925 | |
2001-05 | 0.8753 | |
2001-06 | 0.853 | |
2001-07 | 0.8615 | |
2001-08 | 0.9014 | |
2001-09 | 0.9114 | |
2001-10 | 0.905 | |
2001-11 | 0.8883 | |
2001-12 | 0.8912 | |
2002-01 | 0.8832 | |
2002-02 | 0.8707 | |
2002-03 | 0.8766 | |
2002-04 | 0.886 | |
2002-05 | 0.917 | |
2002-06 | 0.9561 | |
2002-07 | 0.9935 | |
2002-08 | 0.9781 | |
2002-09 | 0.9806 | |
2002-10 | 0.9812 | |
2002-11 | 1.0013 | |
2002-12 | 1.0194 | |
2003-01 | 1.0622 | |
2003-02 | 1.0785 | |
2003-03 | 1.0797 | |
2003-04 | 1.0862 | |
2003-05 | 1.1556 | |
2003-06 | 1.1674 | |
2003-07 | 1.1365 | |
2003-08 | 1.1155 | |
2003-09 | 1.1267 | |
2003-10 | 1.1714 | |
2003-11 | 1.171 | |
2003-12 | 1.2298 | |
2004-01 | 1.2638 | |
2004-02 | 1.264 | |
2004-03 | 1.2261 | |
2004-04 | 1.1989 | |
2004-05 | 1.2 | |
2004-06 | 1.2146 | |
2004-07 | 1.2266 | |
2004-08 | 1.2191 | |
2004-09 | 1.2224 | |
2004-10 | 1.2507 | |
2004-11 | 1.2997 | |
2004-12 | 1.3406 | |
2005-01 | 1.3123 | |
2005-02 | 1.3013 | |
2005-03 | 1.3185 | |
2005-04 | 1.2943 | |
2005-05 | 1.2697 | |
2005-06 | 1.2155 | |
2005-07 | 1.2041 | |
2005-08 | 1.2295 | |
2005-09 | 1.2234 | |
2005-10 | 1.2022 | |
2005-11 | 1.1789 | |
2005-12 | 1.1861 | |
2006-01 | 1.2126 | |
2006-02 | 1.194 | |
2006-03 | 1.2028 | |
2006-04 | 1.2273 | |
2006-05 | 1.2767 | |
2006-06 | 1.2661 | |
2006-07 | 1.2681 | |
2006-08 | 1.281 | |
2006-09 | 1.2722 | |
2006-10 | 1.2617 | |
2006-11 | 1.2888 | |
2006-12 | 1.3205 | |
2007-01 | 1.2993 | |
2007-02 | 1.308 | |
2007-03 | 1.3246 | |
2007-04 | 1.3513 | |
2007-05 | 1.3518 | |
2007-06 | 1.3421 | |
2007-07 | 1.3726 | |
2007-08 | 1.3626 | |
2007-09 | 1.391 | |
2007-10 | 1.4233 | |
2007-11 | 1.4683 | |
2007-12 | 1.4559 | |
2008-01 | 1.4728 | |
2008-02 | 1.4759 | |
2008-03 | 1.552 | |
2008-04 | 1.5754 | |
2008-05 | 1.5554 | |
2008-06 | 1.5562 | |
2008-07 | 1.5759 | |
2008-08 | 1.4955 | |
2008-09 | 1.4342 | |
2008-10 | 1.3266 | |
2008-11 | 1.2744 | |
2008-12 | 1.3511 | |
2009-01 | 1.3244 | |
2009-02 | 1.2797 | |
2009-03 | 1.305 | |
2009-04 | 1.3199 | |
2009-05 | 1.3646 | |
2009-06 | 1.4014 | |
2009-07 | 1.4092 | |
2009-08 | 1.4266 | |
2009-09 | 1.4575 | |
2009-10 | 1.4821 | |
2009-11 | 1.4908 | |
2009-12 | 1.4579 | |
2010-01 | 1.4266 | |
2010-02 | 1.368 | |
2010-03 | 1.357 | |
2010-04 | 1.3417 | |
2010-05 | 1.2563 | |
2010-06 | 1.2223 | |
2010-07 | 1.2811 | |
2010-08 | 1.2903 | |
2010-09 | 1.3103 | |
2010-10 | 1.3901 | |
2010-11 | 1.3654 | |
2010-12 | 1.3221 | |
2011-01 | 1.3371 | |
2011-02 | 1.3656 | |
2011-03 | 1.402 | |
2011-04 | 1.446 | |
2011-05 | 1.4335 | |
2011-06 | 1.4403 | |
2011-07 | 1.4275 | |
2011-08 | 1.4333 | |
2011-09 | 1.3747 | |
2011-10 | 1.3732 | |
2011-11 | 1.3558 | |
2011-12 | 1.3155 | |
2012-01 | 1.291 | |
2012-02 | 1.3238 | |
2012-03 | 1.3208 | |
2012-04 | 1.316 | |
2012-05 | 1.2806 | |
2012-06 | 1.2541 | |
2012-07 | 1.2278 | |
2012-08 | 1.2406 | |
2012-09 | 1.2885 | |
2012-10 | 1.2974 | |
2012-11 | 1.2837 | |
2012-12 | 1.3119 | |
2013-01 | 1.3304 | |
2013-02 | 1.3347 | |
2013-03 | 1.2953 | |
2013-04 | 1.3025 | |
2013-05 | 1.2983 | |
2013-06 | 1.3197 | |
2013-07 | 1.3088 | |
2013-08 | 1.3314 | |
2013-09 | 1.3364 | |
2013-10 | 1.3646 | |
2013-11 | 1.3491 | |
2013-12 | 1.3708 | |
2014-01 | 1.3624 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment