Skip to content

Instantly share code, notes, and snippets.

@tlfrd
Last active January 1, 2020 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tlfrd/cfb80089b4d55b21f1ce18bae6842fff to your computer and use it in GitHub Desktop.
Save tlfrd/cfb80089b4d55b21f1ce18bae6842fff to your computer and use it in GitHub Desktop.
Heat Map
license: mit

Visualising the results of Imperial's 2017 NSS as a Heat Map.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400, 600" rel="stylesheet">
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.score rect {
fill: none;
}
text {
opacity: 0.7;
font-family: 'Open Sans', sans-serif;
}
.legend-labels {
font-size: 16px;
}
.score-labels {
font-size: 15px;
}
.x-label {
font-weight: 600;
}
.uni-labels {
font-size: 14px;
}
.annotation {
font-size: 12px;
}
</style>
</head>
<body>
<script>
var margin = {top: 100, right: 100, bottom: 125, left: 250};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
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 + ")");
var negativeScale = d3.scaleLinear().range(["red", "white"]);
var positiveScale = d3.scaleLinear().range(["white", "green"]);
var config = {};
function getValues(d) {
for (var i = 1; i <= 27; i++) {
d[i] = +d[i];
}
return d;
}
d3.csv("nss-results.csv", getValues, function(error, results) {
if (error) throw error;
var englandAverage = results[results.length - 2],
imperialAverage = results[results.length - 1];
results = results.slice(0, -2);
results.forEach(function(d) {
var eng = [],
imp = [];
for (var i = 1; i <= 27; i++) {
eng[i - 1] = (d[i] - englandAverage[i]).toPrecision(2);
imp[i - 1] = (d[i] - imperialAverage[i]).toPrecision(2);
}
d.englandAvgDiff = eng;
d.imperialAvgDiff = imp;
d.engAvgDiffSum = d3.sum(d.englandAvgDiff);
d.impAvgDiffSum = d3.sum(d.imperialAvgDiff);
});
results.sort(function(a, b) {
if (a.engAvgDiffSum < b.engAvgDiffSum) return 1;
if (a.engAvgDiffSum > b.engAvgDiffSum) return -1;
return 0;
})
var rectWidth = width / results[0].englandAvgDiff.length,
rectHeight = height / results.length;
var grid = svg.append("g")
.attr("class", "grid");
var max = d3.max(results, function(d) {
return d3.max(d.englandAvgDiff, function(x) {
return +x;
})
});
var min = d3.min(results, function(d) {
return d3.min(d.englandAvgDiff, function(x) {
return +x;
})
});
var maxAbs = Math.max(Math.abs(max), Math.abs(min));
negativeScale.domain([-maxAbs, 0]);
positiveScale.domain([0, maxAbs]);
var xLabel = svg.append("g")
.attr("transform", "translate(" + [width / 2, -margin.top / 2] + ")")
.append("text")
.attr("class", "x-label")
.attr("text-anchor", "middle")
.text("How each Department Scores per NSS Question");
var annotation = svg.append("g")
.attr("transform", "translate(" + [width / 2, height + margin.bottom / 3] + ")");
annotation.append("text")
.attr("class", "annotation")
.text("*Molecular Biology, Biophysics, and Biochemisty")
var universities = grid.selectAll("g")
.data(results)
.enter().append("g")
.attr("class", "university")
.attr("transform", (d, i) => "translate(" + [0, i * rectHeight] + ")");
var universityLabels = universities.append("text")
.attr("class", "uni-labels")
.attr("text-anchor", "end")
.attr("x", -10)
.attr("y", rectHeight)
.attr("dy", -3)
.text(d => d.department);
var scoreLabels = grid.append("g")
.attr("class", "score-labels")
.selectAll("text")
.data(d3.range(results[0].englandAvgDiff.length))
.enter().append("text")
.attr("x", d => (rectWidth * d) + rectWidth / 2)
.attr("dy", -10)
.attr("text-anchor", "middle")
.text(d => d + 1);
var scores = universities.selectAll("g")
.data(d => d.englandAvgDiff)
.enter().append("g")
.attr("class", "score")
.attr("transform", (d, i) => "translate(" + [i * rectWidth, 0] + ")");
var scoreRect = scores.append("rect")
.attr("width", rectWidth + 1)
.attr("height", rectHeight + 2)
.style("fill", function(d) {
if (d < 0) {
return negativeScale(d);
} else if (d > 0) {
return positiveScale(d);
} else {
return "#fff";
}
});
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + [0, height + 50] + ")");
var colours = legend.selectAll("rect")
.data(d3.range(-maxAbs, maxAbs + maxAbs/3, maxAbs/3))
.enter().append("rect")
.attr("x", (d, i) => i * rectWidth)
.attr("width", rectWidth + 1)
.attr("height", rectHeight)
.style("fill", function(d) {
if (d < 0) {
return negativeScale(d);
} else if (d > 0) {
return positiveScale(d);
} else {
return "#fff";
}
});
var legendOffsets = 30;
var legendLabels = legend.append("g")
.attr("class", "legend-labels")
.attr("transform", "translate(" + [-legendOffsets, -10] + ")")
legendLabels.append("text")
.attr("text-anchor", "start")
.text("← Below Avg")
legendLabels.append("text")
.attr("x", rectWidth * 7 + legendOffsets * 2)
.attr("text-anchor", "end")
.text("Above Avg →")
});
</script>
</body>
department 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
Medicine 0.88 0.82 0.91 0.80 0.75 0.82 0.93 0.73 0.76 0.56 0.55 0.85 0.74 0.72 0.76 0.77 0.75 0.88 0.93 0.91 0.78 0.91 0.93 0.80 0.72 0.75 0.90
Biomedical Sciences 0.88 0.74 0.89 0.86 0.80 0.77 0.70 0.50 0.68 0.35 0.59 0.73 0.68 0.59 0.35 0.53 0.59 0.71 0.84 0.85 0.64 0.88 0.92 0.83 0.64 0.56 0.70
Biology 0.87 0.84 0.89 0.82 0.83 0.81 0.71 0.75 0.62 0.71 0.48 0.85 0.66 0.67 0.72 0.86 0.75 0.88 0.82 0.86 0.52 0.89 0.87 0.69 0.62 0.47 0.81
MBBPBC* 0.90 0.78 0.83 0.82 0.83 0.86 0.80 0.66 0.64 0.70 0.52 0.82 0.58 0.62 0.67 0.86 0.86 0.78 0.85 0.86 0.51 0.89 0.88 0.74 0.74 0.51 0.83
Chemistry 0.84 0.75 0.89 0.75 0.80 0.74 0.82 0.51 0.56 0.59 0.53 0.75 0.60 0.52 0.52 0.74 0.67 0.85 0.84 0.89 0.57 0.78 0.79 0.63 0.48 0.53 0.73
Physics 0.82 0.73 0.86 0.71 0.71 0.68 0.60 0.47 0.43 0.46 0.56 0.82 0.56 0.62 0.57 0.70 0.70 0.78 0.81 0.87 0.45 0.76 0.82 0.54 0.50 0.40 0.67
Geology 0.99 0.97 0.96 0.93 0.93 0.94 0.97 0.93 0.87 0.97 0.94 0.97 0.97 0.99 0.99 0.91 0.99 1.00 0.96 1.00 0.89 0.94 0.99 0.99 0.97 0.86 0.97
Mathematics 0.87 0.76 0.83 0.79 0.85 0.70 0.62 0.57 0.69 0.53 0.55 0.87 0.68 0.68 0.76 0.73 0.81 0.91 0.82 0.91 0.59 0.70 0.88 0.78 0.67 0.52 0.78
Computer Science 0.82 0.79 0.94 0.82 0.85 0.87 0.91 0.54 0.79 0.54 0.63 0.90 0.78 0.64 0.74 0.74 0.87 0.92 0.89 0.93 0.71 0.98 0.95 0.85 0.80 0.66 0.86
Bioengineering 0.92 0.91 0.97 0.86 0.91 0.97 0.85 0.57 0.74 0.77 0.66 0.91 0.80 0.69 0.86 0.82 0.85 0.80 0.81 0.91 0.85 0.94 0.92 0.94 0.83 0.57 0.97
Mechanical Engineering 0.91 0.83 0.93 0.87 0.91 0.90 0.88 0.77 0.81 0.78 0.83 0.90 0.87 0.88 0.85 0.83 0.92 0.85 0.88 0.89 0.74 0.99 0.99 0.84 0.89 0.57 0.86
Aerospace Engineering 0.71 0.67 0.81 0.75 0.72 0.77 0.74 0.65 0.67 0.43 0.57 0.86 0.73 0.59 0.70 0.70 0.75 0.90 0.87 0.87 0.57 0.96 0.86 0.61 0.57 0.53 0.78
EEE 0.88 0.81 0.92 0.85 0.88 0.89 0.86 0.75 0.71 0.60 0.65 0.86 0.69 0.68 0.80 0.79 0.88 0.89 0.88 0.97 0.72 0.96 0.92 0.80 0.85 0.66 0.86
Civil Engineering 0.93 0.81 0.94 0.88 0.86 0.89 0.93 0.69 0.75 0.87 0.69 0.96 0.90 0.82 0.90 0.90 0.90 0.96 0.96 0.94 0.85 0.97 0.94 0.92 0.79 0.77 0.94
Chemical Engineering 0.86 0.79 0.88 0.94 0.88 0.87 0.86 0.75 0.70 0.61 0.68 0.95 0.74 0.74 0.84 0.82 0.95 0.80 0.84 0.86 0.70 0.96 0.94 0.85 0.92 0.58 0.84
Materials 0.85 0.78 0.85 0.73 0.91 0.90 0.73 0.54 0.69 0.65 0.69 0.79 0.71 0.73 0.66 0.82 0.77 0.94 0.89 0.98 0.72 0.91 0.85 0.80 0.65 0.71 0.87
England Average 0.89 0.83 0.85 0.82 0.84 0.85 0.82 0.72 0.73 0.73 0.74 0.86 0.79 0.75 0.71 0.79 0.77 0.83 0.87 0.86 0.72 0.86 0.84 0.76 0.62 0.58 0.84
Imperial Average 0.87 0.80 0.89 0.82 0.83 0.83 0.82 0.66 0.69 0.62 0.62 0.87 0.73 0.70 0.74 0.78 0.81 0.87 0.87 0.91 0.68 0.90 0.90 0.78 0.73 0.61 0.84
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment