These visulizations are built on top of the Scatterplot and Bar chart examples presented on Piazza. This was originally forked from asielen's block: Reusable Line Chart v2, an implementation of a reusable responsive multiline chart, but it largely wasn't used
Contents:
forked from Tedables's block: Homework 1
xxxxxxxxxx
<!--Level of Education vs Time spent Working
built largely on top of example linked in piazza:
https://bl.ocks.org/d3noob/402dd382a51a4f6eea487f9a35566de0
From previous graphs, it is clear that you get more money with a higher degree, but you also likely spend much more time working!
-->
<html>
<meta charset="utf-8">
<!-- Example based on https://bl.ocks.org/mbostock/3887118 -->
<!-- Tooltip example from https://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html -->
<style>
body {
font: 11px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
.tooltip {
position: absolute;
width: 200px;
height: 28px;
pointer-events: none;
}
</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<!--
<button id="2AHisto" value="2AHisto">Average Income Histogram</button><button id="2JHisto">Median Income Histogram</button><br>
<button id="2ALine" value="2ALine">Average Income Line</button><button id="2JLine">Median Income Line</button><br>
<button id="2ABars" value="2ABars">Average Income, Earnings, months worked </button><button id="2JBars">Median Income, Earnings, months worked</button><br>
<svg id="svg"></svg>
<script type="text/javascript" src=csv.js>
d3.select("#2AHisto").on("click", function(d,i)
{
table2AHisto();
})
d3.select("#2JHisto").on("click", function(d,i)
{
table2JHisto();
})
d3.select("#2ALine").on("click", function(d,i)
{
table2ALine();
})
d3.select("#2JLine").on("click", function(d,i)
{
table2JLine();
})
d3.select("#2ABars").on("click", function(d,i)
{
table2ABars();
})
d3.select("#2JBars").on("click", function(d,i)
{
table2JBars();
})
table2JHisto();
</script>
-->
<script>
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var x = d3.scaleBand()
.range([0, width])
.padding(0.1);
var y = d3.scaleLinear()
.range([height, 0])
// define the line
var valueline = d3.line()
.x(function(d) { return x(d["Highest level completed"]); })
.y(function(d) { return y(d["Months worked"]); });
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
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 + ")");
// get the data
d3.csv("Table_2A.csv", function(error, data) {
if (error) throw error;
// format the data: divide income by percentage of time worked
data.forEach(function(d) {
d["Total income"] = +Number(d["Total income"].replace(/[^0-9\.]+/g,""));
d["Months worked"] = +d["Months worked"];
});
var maxIncome = d3.max(data, function(d) { return d["Total income"]; })
var minIncome = d3.min(data, function(d) { return d["Total income"]; })
var maxTime = 4;
data.forEach(function(d) {
d.time = d["Months worked"] / maxTime;
d.incomeNorm = d["Total income"] / maxIncome;
d.net = d.incomeNorm / d.time;
});
//for line of regression
var max = d3.max(data, function(d) { return d["Months worked"]; })
var min = d3.min(data, function(d) { return d["Months worked"]; })
// Scale the range of the data in the domains
x.domain(data.map(function(d) { return d["Highest level completed"]; }));
y.domain([d3.min(data, function(d) { return d["Months worked"]; }), d3.max(data, function(d) { return d["Months worked"]; })+0.3]);
//add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 6)
.attr("d", valueline);
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom) + ")")
.style("text-anchor", "middle")
.style("font-weight", "bold")
.text("Level of Education");
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y));
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("font-weight", "bold")
.text("Months worked (of last 4)");
//code taken from https://stackoverflow.com/questions/20507536/d3-js-linear-regression
function linearRegression(y,x){
var lr = {};
var n = y.length;
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_xx = 0;
var sum_yy = 0;
for (var i = 0; i < y.length; i++) {
sum_x += x[i];
sum_y += y[i];
sum_xy += (x[i]*y[i]);
sum_xx += (x[i]*x[i]);
sum_yy += (y[i]*y[i]);
}
lr['slope'] = (n * sum_xy - sum_x * sum_y) / (n*sum_xx - sum_x * sum_x);
lr['intercept'] = (sum_y - lr.slope * sum_x)/n;
lr['r2'] = Math.pow((n*sum_xy - sum_x*sum_y)/Math.sqrt((n*sum_xx-sum_x*sum_x)*(n*sum_yy-sum_y*sum_y)),2);
return lr;
};
/*
* Source: https://stevegardner.net/2012/06/11/javascript-code-to-calculate-the-pearson-correlation-coefficient/
*/
function getPearsonCorrelation(x, y) {
var shortestArrayLength = 0;
if(x.length == y.length) {
shortestArrayLength = x.length;
} else if(x.length > y.length) {
shortestArrayLength = y.length;
console.error('x has more items in it, the last ' + (x.length - shortestArrayLength) + ' item(s) will be ignored');
} else {
shortestArrayLength = x.length;
console.error('y has more items in it, the last ' + (y.length - shortestArrayLength) + ' item(s) will be ignored');
}
var xy = [];
var x2 = [];
var y2 = [];
for(var i=0; i<shortestArrayLength; i++) {
xy.push(x[i] * y[i]);
x2.push(x[i] * x[i]);
y2.push(y[i] * y[i]);
}
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_x2 = 0;
var sum_y2 = 0;
for(var i=0; i< shortestArrayLength; i++) {
sum_x += x[i];
sum_y += y[i];
sum_xy += xy[i];
sum_x2 += x2[i];
sum_y2 += y2[i];
}
var step1 = (shortestArrayLength * sum_xy) - (sum_x * sum_y);
var step2 = (shortestArrayLength * sum_x2) - (sum_x * sum_x);
var step3 = (shortestArrayLength * sum_y2) - (sum_y * sum_y);
var step4 = Math.sqrt(step2 * step3);
var answer = step1 / step4;
return answer;
}
//append the mean as a red dashed line
var mean = d3.mean(data,function(d) { return y(d["Months worked"])})
//MEAN
svg.append("line")
.attr("x1", 0)
.attr("y1", mean)
.attr("x2", width)
.attr("y2", mean)
.style("stroke-dasharray", ("5, 5"))
.attr("stroke-width", 3)
.attr("stroke", "red");
//REGRESSION
var lr = linearRegression(y,x);
var incomes = [];
var monthsWorked = [];
data.forEach(function(d) {
incomes.push(d["Total income"])
monthsWorked.push(d["Months worked"])
});
var pcc = getPearsonCorrelation(incomes, monthsWorked);
svg.append("line")
.attr("x1", x(0))
.attr("y1", y(min))
.attr("x2", width)
.attr("y2", y( (max * lr.slope) + lr.intercept ))
.style("stroke-dasharray", ("10, 15"))
.attr("stroke-width", 2)
.attr("stroke", "green");
/*
svg.append("text")
.attr("x", margin.left * 0.8)
.attr("y", height /6)
.attr("text-anchor", "left")
.style("font-size", "12px")
.style('fill', 'black')
.text("Pearson Correlation of income vs time worked: " + pcc);
*/
});
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top /20))
.attr("text-anchor", "middle")
.style("font-size", "25px")
.style("text-decoration", "bold")
.text("Level of Education vs Time spent Working");
svg.append("text")
.attr("x", margin.left * 0.8)
.attr("y", height /35)
.attr("text-anchor", "left")
.style("font-size", "12px")
.style('fill', 'red')
.text("Red line = Mean");
svg.append("text")
.attr("x", margin.left * 0.8)
.attr("y", height /9)
.attr("text-anchor", "left")
.style("font-size", "12px")
.style('fill', 'green')
.text("Green line = Line of Regression");
</script>
</body>
</html>
Modified http://d3js.org/d3.v4.min.js to a secure url
https://d3js.org/d3.v4.min.js