Applying linear regression to the Party Trend chart.
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
svg {
margin-left: auto; margin-right: auto;
display: block;
}
line,
rect {
shape-rendering: crispEdges;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke-width: 1.5px;
}
circle.dot {
fill: #FFF !important;
stroke-width: 1.5px !important;
}
/** Grid lines BEGIN */
/** https://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html */
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
}
.grid path {
stroke-width: 0;
}
/** Grid lines END */
</style>
</head>
<body>
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="d3.min.js?v=3.2.8"></script>
<script src="https://rawgithub.com/tmcw/simple-statistics/master/src/simple_statistics.js?v=0.8.0"></script>
<script type="text/javascript"charset="utf-8">
// Settings
var width = 440,
height = 400,
padding = 30;
var margin = {
'top': 30,
'right': 125,
'bottom': 30,
'left': 30
};
margin.hor = margin.left + margin.right;
margin.ver = margin.top + margin.bottom;
// Config
var dataset = "data.csv",
parseDate = d3.time.format("%m/%d/%Y").parse,
electionDate = "", // "05/15/2015",
yAxisTitle = "Votes (%)",
dateValue = "Date",
instituteValue = "Polling Firm"
showLineChart = false,
showAllParties = false;
if (showAllParties === false) {
var parties = ["A"];
}
var displayInstitutes = (showAllParties === false && parties.length === 1) ? true : false;
var ignoreFilter = [
"Lead",
"Red (A+B+F+Ø)",
"Blue (V+O+I+C+K)",
"Polling Firm"
]
ignoreFilter.push(dateValue);
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var instituteColor = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(7)
.tickSubdivide(2);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(function(d) { return d + "%"; });
var line = d3.svg.line()
// .interpolate("linear")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.dataValue); });
var svg = d3.select("body").append("svg")
.attr({
"width": width + margin.left + margin.right,
"height": height + margin.top + margin.bottom
})
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv(dataset, function(error, data) {
color.domain(
d3.keys(data[0])
.filter(function(key) {
if (ignoreFilter.indexOf(key) === -1) return key;
}));
instituteColor.domain(
d3.nest().key(function(d) {
return d[instituteValue];
})
.entries(data)
.map(function(d) { return d.key; })
);
data.forEach(function(d) {
d.date = parseDate(d[dateValue]);
});
var valueColumns = color.domain()
.map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
dataValue: parseFloat(d[name]),
institute: d[instituteValue]
};
})
};
});
if (electionDate === "") {
x.domain(d3.extent(data, function(d) {
return d.date; }));
} else {
x.domain([
d3.min(data, function(d) { return d.date; }),
parseDate(electionDate)
]);
}
y.domain([
0, d3.max(valueColumns, function(c) { return d3.max(c.values, function(v) { return v.dataValue; }); })
]);
if (showAllParties === false && parties.length === 1) {
// Linear regression
var regLine = ss.linear_regression().data(data.map(function(d) {
return [+d.date, parseFloat(d[parties[0]])];
})).line();
// Create a line based on the beginning and endpoints of the range
var regLineData = x.domain().map(function(x) { // change if electionDate
return {
date: x,
dataValue: regLine(x)
};
});
}
/**
if (showAllParties === false && parties.length === 1) {
y.domain(d3.extent(data, function(d) {
return d[parties[0]];
}))
}
else {
y.domain([
0, d3.max(valueColumns, function(c) { return d3.max(c.values, function(v) { return v.dataValue; }); })
]);
}
*/
// Append x axis
svg.append("g")
.attr({
"class": "x axis",
"transform": "translate(0," + height + ")"
})
.call(xAxis);
// Append y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr({
"transform": "rotate(-90)",
"y": 6,
"dy": ".71em"
})
.style("text-anchor", "end")
.text(yAxisTitle);
// Gridlines
//
// https://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html
svg.append("g")
.attr({
"class": "grid",
"transform": "translate(0," + height + ")"
})
.call(xAxis
.tickSize(-height, 0, 0)
.tickFormat("")
.ticks(d3.time.months, 1)
);
// Graph
// Create graph
var graph = svg.selectAll(".graph")
.data(valueColumns.filter(function(d) {
return showAllParties === true ? d.name : parties.indexOf(d.name) !== -1;
}))
.enter().append("g")
.attr("class", "graph");
if (showLineChart === true) {
// "Connect the dots"
graph.append("path")
.attr({
"class": "line",
"d": function(d) { return line(d.values); }
})
.style("stroke", function(d) {
return (showAllParties === false && parties.length === 1) ? "#777" : color(d.name);
});
}
// Add dots
var dots = svg.selectAll(".dot")
.data(valueColumns.filter(function(d) {
return showAllParties === true ? d.name : parties.indexOf(d.name) !== -1;
}))
.enter()
var n = 0;
while (n < data.length) {
dots.append("circle")
.attr({
"class": "dot",
"r": 2,
"cx": function(d) {
return x(d.values[n].date);
},
"cy": function(d) {
return y(d.values[n].dataValue);
},
"stroke": function(d) {
return displayInstitutes === false ? color(d.name) : instituteColor(d.values[n].institute);
}});
n += 1;
}
if (showAllParties === false && parties.length === 1) {
// Regression line
svg.append("path")
.datum(regLineData)
.attr({
"class": "reg",
"d": line
})
.style("stroke", "777");
}
var legendSize = 18,
legendSpacing = 20,
legendData = displayInstitutes === false ? color.domain().slice() : instituteColor.domain().slice();
var legend = svg.selectAll(".legend")
// Change for all-chart
.data(legendData)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + 0 + "," + i * (legendSize + 2) + ")"; });
legend.append("rect")
.attr("x", width + legendSpacing)
.attr("width", legendSize)
.attr("height", legendSize)
.style("fill", function(d) {
return (displayInstitutes === false) ? color : instituteColor(d);
});
legend.append("text")
.attr("x", width + legendSpacing + legendSize + 6)
.attr("y", legendSize/2)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { return d; });
});
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://rawgithub.com/tmcw/simple-statistics/master/src/simple_statistics.js?v=0.8.0