A simple linear regression test with Math.js using normal equations solution (based on Coursera's Machine Learning Course). You can view the interpolated values moving the mouse over the calculated line.
Run "bower install" and watch the console output.
xxxxxxxxxx
<html>
<head>
<title>Linear regression test</title>
<style>
path {
stroke: steelblue; stroke-width: 2; fill: none;
}
.axis path, .axis line {
fill: none;
stroke: grey;
stroke-width: 1; shape-rendering: crispEdges;
}
.dot {
stroke: black;
}
div.tooltip {
position: absolute; text-align: center;
width: 80px;
height: 28px;
padding: 2px;
font: 12px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px; pointer-events: none;
}
</style>
</head>
<body>
<!-- <script src="bower_components/d3/d3.min.js"></script>
<script src="bower_components/mathjs/dist/math.js"></script> -->
<script src="d3.min.js"></script>
<script src="math.min.js"></script>
<script type="text/javascript">
var math = mathjs();
var linear_regression = function(X, y) {
var m = y.length;
X = math.concat(math.ones(m,1), X);
y = math.matrix(y);
var tr = math.transpose(X);
var tr_X = math.multiply(tr, X);
var tr_y = math.multiply(tr, y);
var theta = math.multiply( math.inv(tr_X), tr_y );
return function() {
var args = Array.prototype.slice.call(arguments);
return math.multiply(math.matrix(math.concat([1], args)), theta);
}
}
console.group("lineal");
var age_weight = [{"age":12,"weight":58},{"age":8,"weight":42},{"age":10,"weight":51},{"age":11,"weight":54},{"age":7,"weight":40},{"age":7,"weight":39},{"age":10,"weight":49},{"age":14,"weight":56}];
var X = age_weight.map(function(d){ return [+d.age]; }),
y = age_weight.map(function(d){ return [+d.weight]; }),
f = linear_regression(X , y);
console.table(age_weight.sort(function(a, b) { return +a.age - b.age; }));
console.log("Weight for a child 6 years old:",f(6));
console.log("Weight for a child 7 years old:",f(7));
console.log("Weight for a child 9 years old:",f(9));
console.log("Weight for a child 15 years old:",f(15));
console.log("Weight for a child 12 years old:",f(12));
console.groupEnd();
draw_chart(age_weight, f, "age", "weight");
function draw_chart(data, fn, xLabel, yLabel) {
var extent = d3.extent(data, function(d) { return d[xLabel]; }),
range = d3.range(extent[0], extent[1], 1);
var regression = data.map(function(d) {
var ob = {};
ob[xLabel] = d[xLabel];
ob[yLabel] = f(d[xLabel]);
return ob;
});
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 500 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom")
.ticks(10);
var yAxis = d3.svg.axis().scale(y)
.orient("left")
.ticks(10);
var line = d3.svg.line()
.x(function(d) { return x(d[xLabel]); })
.y(function(d) { return y(d[yLabel]); })
;
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(d3.extent(data, function(d) { return d[xLabel]; }));
y.domain(d3.extent(data, function(d) { return d[yLabel]; }));
svg.selectAll(".dot")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return x(d[xLabel]); })
.attr("cy", function(d) { return y(d[yLabel]); })
.attr("r", 2)
.attr("class", "dot");
var div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.append("path")
.attr("d", line(regression))
.on("mousemove", function(d) {
var _x = d3.mouse(this)[0],
_y = d3.mouse(this)[1];
div.transition()
.duration(200)
.style({
"opacity": .9,
left: d3.event.pageX + 20 + 'px',
top: d3.event.pageY + 10 + 'px'
});
div.html(xLabel + ": " + d3.round(x.invert(_x), 2) + " " + yLabel + ": " + d3.round(y.invert(_y), 2));
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
}
</script>
</body>
</html>