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/6e20a23a1479b46dcfdc50efec51ee3b to your computer and use it in GitHub Desktop.
Save tlfrd/6e20a23a1479b46dcfdc50efec51ee3b to your computer and use it in GitHub Desktop.
Heat Map II
license: mit

Visualising the results of Imperial's Staff Survey for Felix.

forked from tlfrd's block: Heat Map

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.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; }
div.tooltip{
position: absolute;
text-align: center;
padding: 5px;
font-size: 12px;
font-family: 'Open Sans', sans-serif;
background-color: white;
border: 1px #b7b7b7 solid;
pointer-events: none;
width: 50px;
}
text {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
}
.title {
font-size: 20px;
}
rect {
stroke: white;
}
</style>
</head>
<body>
<script>
var margin = {top: 125, right: 100, bottom: 100, left: 275};
var width = 900 - 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 + ")");
d3.csv("staffsurvey.csv", (error, data) => {
if (error) throw error;
var formattedData = formatData(data);
var extent = getExtent(formattedData);
// Create colour scale
var colourScale = d3.scaleLinear();
colourScale.range(["#f9f9ff", "#0000FF"])
colourScale.domain([extent[1], extent[0]]);
drawHeatMap(formattedData, {height: height, width: width, xLength: formattedData[0].facultyResults.length, rowLabelXPadding: 10, columnLabelYPadding: 10}, colourScale);
});
// Get extent of percentage
function getExtent(data) {
var minPercentage = d3.min(data, d => {
return d3.min(d.facultyResults, d1 => {
if (d1.percentage) {
return d1.percentage;
} else {
return 100;
}
});
});
var maxPercentage = d3.max(data, d => {
return d3.max(d.facultyResults, d1 => {
if (d1.percentage) {
return d1.percentage;
} else {
return 0;
}
});
});
return [minPercentage, maxPercentage];
}
// Format data into nice arrays
function formatData(data) {
var questions = [];
data.forEach(d => {
var facultiesArray = [];
for (var faculty in d) {
if (faculty != "Question Class") {
facultiesArray.push({
faculty: faculty,
percentage: d[faculty].slice(0, -1)
});
}
}
questions.push({
questionClass: d["Question Class"],
facultyResults: facultiesArray
});
});
return questions;
}
// Refactor and pass position of label via config
function showLabel(d) {
var coords = [d3.event.clientX, d3.event.clientY];
var top = coords[1] + 30,
left = coords[0] - 50;
d3.select(".tooltip")
.style("top", top + "px")
.style("left", left + "px")
.transition()
.duration(200)
.style("opacity", 1)
d3.select(".tooltip")
.html(d.percentage + "%")
}
function moveLabel() {
var coords = [d3.event.clientX, d3.event.clientY];
var top = coords[1] + 30,
left = coords[0] - 50;
d3.select(".tooltip")
.style("top", top + "px")
.style("left", left + "px");
}
function hideLabel(d) {
d3.select(".tooltip")
.transition()
.duration(200)
.style("opacity", 0);
}
// Draw the heatmap
function drawHeatMap(data, config, colourScale) {
var rectWidth = config.width / config.xLength,
rectHeight = config.height / data.length;
var rowGroups = svg.selectAll("g")
.data(data).enter()
.append("g")
.attr("class", "row-group")
.attr("transform", (d, i) => "translate(" + [0, i * rectHeight] + ")");
var rects = rowGroups.selectAll("rect")
.data(d => d.facultyResults).enter()
.append("rect")
.attr("class", "row")
.attr("width", rectWidth)
.attr("height", rectHeight)
.attr("x", (d, i) => i * rectWidth)
.style("fill", d => colourScale(d.percentage))
.on("mouseover", showLabel)
.on("mousemove", moveLabel)
.on("mouseout", hideLabel);
// Refactor
var title = svg.append("text")
.attr("y", -50)
.attr("x", width / 2)
.attr("text-anchor", "middle")
.attr("class", "title")
.text("Percentage of Postitive Responses for Question Classes by Department")
// Refactor
var rowLabels = rowGroups.append("text")
.attr("x", -config.rowLabelXPadding)
.attr("y", rectHeight / 1.5)
.attr("text-anchor", "end")
.text(d => d.questionClass);
// Refactor
var columnLabels = svg.append("g")
.attr("class", "columnLabels")
.selectAll("text")
.data(data[0].facultyResults).enter()
.append("text")
.attr("text-anchor", "middle")
.attr("x", (d, i) => i * rectWidth + (rectWidth / 2))
.attr("y", -config.columnLabelYPadding)
.text(d => d.faculty);
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + [0, height + rectHeight] + ")")
var legendLinear = d3.legendColor()
.shapeWidth(rectWidth)
.shapeHeight(rectHeight)
.shapePadding(0)
.orient('horizontal')
.scale(colourScale)
.labelFormat(d => Math.round(d) + "%");
legend.call(legendLinear);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
}
</script>
</body>
Question Class Overall Aero Bioeng Chem Eng Civil Computing ESE EEE Materials Mech Eng Dyson Business Medicine CEP Chem Life Science Maths Physics
Your Role 71% 64% 73% 70% 71% 67% 76% 72% 70% 76% 69% 72% 68% 70% 70% 68% 75% 70%
Your Development 61% 55% 66% 65% 61% 57% 72% 65% 65% 65% 70% 61% 56% 51% 64% 54% 72% 62%
Reward and Recognition 59% 48% 57% 52% 48% 44% 57% 52% 55% 62% 59% 60% 55% 58% 46% 52% 58% 52%
Safety 88% 80% 88% 85% 91% 82% 92% 92% 86% 86% 82% 86% 88% 82% 92% 93% 86% 92%
Health and Wellbeing 68% 63% 65% 66% 71% 58% 72% 68% 68% 67% 59% 67% 65% 63% 63% 66% 64% 67%
Your Line Manager 69% 53% 69% 78% 71% 65% 75% 75% 72% 74% 77% 69% 65% 61% 72% 62% 79% 66%
Your Department 66% 50% 72% 63% 62% 64% 68% 64% 67% 61% 68% 70% 55% 59% 64% 56% 70% 63%
Your Faculty 40% 31% 47% 43% 33% 33% 44% 34% 44% 37% 55% 48% 32% 41% 42% 33% 34% 31%
College Senior Leadership 41% 27% 42% 44% 48% 26% 44% 37% 40% 40% 47% 51% 30% 35% 44% 34% 36% 35%
Communication 52% 45% 54% 54% 58% 45% 54% 47% 49% 46% 62% 48% 47% 51% 54% 46% 43% 44%
Equality, Diversity, and Inclusion 74% 63% 67% 70% 72% 65% 67% 67% 75% 76% 69% 79% 67% 70% 74% 71% 74% 73%
Perceptions of the College 74% 73% 77% 75% 83% 70% 77% 83% 76% 78% 80% 79% 68% 74% 69% 66% 77% 74%
Next Steps 53% 33% 61% 57% 53% 46% 50% 55% 50% 50% 64% 49% 45% 61% 53% 50% 55% 56%
Question Class Overall Business School Engineering Medicine FoNS
Your Role 71% 72% 72% 69% 71%
Your Development 61% 61% 64% 59% 61%
Reward and Recognition 59% 60% 54% 57% 55%
Safety 88% 86% 87% 88% 91%
Health and Wellbeing 68% 67% 67% 67% 66%
Your Line Manager 69% 69% 72% 68% 68%
Your Department 66% 70% 65% 61% 63%
Your Faculty 40% 48% 41% 39% 37%
College Senior Leadership 41% 51% 40% 37% 37%
Communication 52% 48% 51% 51% 48%
Equality, Diversity, and Inclusion 74% 79% 77% 71% 72%
Perceptions of the College 74% 79% 77% 71% 72%
Next Steps 53% 49% 53% 51% 55%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment