Skip to content

Instantly share code, notes, and snippets.

@delormev
Last active May 9, 2017 13:39
Show Gist options
  • Save delormev/896c4373465573a68684 to your computer and use it in GitHub Desktop.
Save delormev/896c4373465573a68684 to your computer and use it in GitHub Desktop.
Alzheimer

## Learn D3js: Part 2 - Data binds & updates

Features:

  • data loading & processing
  • scales
  • data / graph updates
  • transitions (with delay)
#chart {
margin: 5px;
}
#chart .axis path, .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
#chart .axis text {
font-family: sans-serif;
font-size: 11px;
}
#chart .legend text {
font-family: sans-serif;
font-size: 13px;
}
#chart .expand text {
font-weight: bold;
}
#chart .expand:hover {
cursor: pointer;
}
Region Type GBD Region Sub-Region Over 60 population (millions; 2015) Crude estimated prevalence (%; 2015) Number of people with dementia (millions; 2015) Number of people with dementia (millions; 2030) Number of people with dementia (millions; 2050) Proportionate increases (%; 2015-2013) Proportionate increases (%; 2015-2050)
Global Asia Asia 485.83 4.7 22.85 38.53 67.18 69 194
Local Asia Australasia 5.80 6.7 0.39 0.62 1.02 59 163
Local Asia Asia Pacific High Income 52.21 7.0 3.64 5.68 7.81 56 115
Local Asia Oceania 0.64 3.5 0.02 0.04 0.09 83 289
Local Asia Asia Central 7.43 4.2 0.31 0.44 0.88 43 184
Local Asia Asia East 218.18 4.5 9.77 16.60 28.64 70 193
Local Asia Asia South 139.85 3.7 5.13 8.61 16.65 68 225
Local Asia Asia Southeast 61.72 5.8 3.60 6.55 12.09 82 236
Global Europe Europe 176.61 5.9 10.46 13.42 18.66 28 78
Local Europe Europe Western 107.89 6.9 7.45 9.99 14.32 34 92
Local Europe Europe Central 26.92 4.0 1.07 1.39 1.90 30 78
Local Europe Europe East 41.80 4.6 1.94 2.03 2.44 4 26
Global America America 147.51 6.4 9.44 15.75 29.86 67 216
Local America North America 74.88 6.4 4.78 7.28 11.74 52 145
Local America Caribbean 5.78 6.5 0.38 0.60 1.07 60 183
Local America LA Andean 5.51 6.1 0.34 0.64 1.43 88 322
Local America LA Central 26.64 5.8 1.54 2.97 6.88 93 348
Local America LA Southern 9.88 7.6 0.75 1.15 2.05 52 172
Local America LA Tropical 24.82 6.7 1.66 3.11 6.70 88 305
Global Africa Africa 87.19 4.6 4.03 6.99 15.76 74 291
Local Africa North Africa & Middle East 38.93 6.0 2.34 4.35 10.04 86 329
Local Africa SSA Central 4.78 3.3 0.16 0.26 0.54 60 238
Local Africa SSA East 19.86 3.5 0.69 1.19 2.77 72 300
Local Africa SSA Southern 6.06 3.9 0.24 0.35 0.58 46 145
Local Africa SSA West 17.56 3.1 0.54 0.85 1.84 58 241
Global World World 897.14 5.2 46.78 74.69 131.45 60 181
// Width, height, margins for axes
var margin = {top: 10, right: 50, bottom: 10, left: 40};
w = 700 - margin.right - margin.left,
h = 500 - margin.top - margin.bottom;
// Data global vars
var alzheimerData,
vizData,
vizKeys,
vizColumns = [],
vizFilters = [function(d) { return (d["GBD Region"] == "World"); },
function(d) { return (d["Region Type"] == "Global" && d["GBD Region"] != "World"); }];
// Colours
var colours = ["#FF6666", "#CCFF66", "#5D2E8C", "#2EC4B6", "#FFA9E7", "#F7A072", "#0FA3B1", "#B388EB", "#FFB4A2", "#6BFFB8", "#B7AD99", "#9395D3", "#B66D0D", "#2176AE", "#69626D", "#FF5964"];
// Set up SVG container
var svgContainer = d3.select("#chart").append("svg")
.attr("class", "container")
.attr("width", w + margin.right + margin.left)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.csv("alzheimer.csv",
function(d) {
d3.keys(d).forEach(function(k) {
if (k.indexOf("Region") == -1) { d[k] = +d[k]; };
if (k.indexOf("millions") != -1) { d[k] = d[k] * 1000000; }
});
return d;
},
function(error, data) {
// Check for error
if (error) { console.log(error); }
alzheimerData = data;
generateViz(vizFilters);
}
);
//Create the Scale we will use for the Axis
var xScale = d3.scale.ordinal()
.rangeRoundBands([0,w - margin.right - margin.left], 0.1);
var yScale = d3.scale.linear()
.range([h - margin.top - margin.bottom,0]).nice();
var cScale = d3.scale.ordinal();
var generateViz = function(filters) {
// Apply data filter
vizData = alzheimerData.filter(filters[0]);
filters = filters.slice(1);
// Select columns we'll need + initialise totals
vizKeys = d3.keys(vizData[0])
.filter(function(d) { return d.indexOf("Number of people with dementia") == 0; })
.map(function(d) { return { name: d, total: +0, year: d.slice(42,46) } });
var key = 1;
// Create column data
vizData.forEach(function(d) {
d3.keys(vizKeys).forEach(function(i) {
if (d3.keys(vizColumns).indexOf(vizKeys[i].name) > -1) {
vizColumns[vizKeys[i].name].push({
key: key,
region: d["GBD Region"],
year: vizKeys[i].year,
y0: vizKeys[i].total,
y1: vizKeys[i].total += d[vizKeys[i].name]
});
} else {
vizColumns[vizKeys[i].name] = [{
key: key,
region: d["GBD Region"],
year: vizKeys[i].year,
y0: vizKeys[i].total,
y1: vizKeys[i].total += d[vizKeys[i].name]
}];
};
key += 1;
});
});
var tmpVizColumns = [];
for (i=0; i < vizKeys.length; i++) {
tmpVizColumns = tmpVizColumns.concat(vizColumns[vizKeys[i].name]);
};
vizColumns = tmpVizColumns;
// Reset scales
regions = vizColumns.map(function(d) { return d.region })
.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
cScale = cScale.domain(regions)
.range(colours.slice(0,regions.length));
yScale = yScale.domain([0,d3.max(vizKeys.map(function(d) { return d.total; }))]);
xScale = xScale.domain(vizKeys.map(function(d) { return d.year; }).sort());
// Create chart
var chartElements = svgContainer.selectAll("rect.barchart")
.data(vizColumns, function(d) {
return d.key;
})
.enter()
.append("rect")
.attr("class", "barchart")
.attr("x", function(d) { return xScale(d.year); } )
.attr("y", yScale(0))
.attr("fill", function(d) { return cScale(d.region); } )
.attr("width", xScale.rangeBand())
.attr("height", 0);
chartElements
.transition()
.duration(500)
.attr("y", function(d) { return yScale(d.y1); } )
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } );
// Axes
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
svgContainer.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - margin.bottom - margin.top) + ")")
.call(xAxis);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.tickFormat(d3.format("s"));
svgContainer.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 10)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Population with Dementia");
// Legend
var legend = svgContainer.selectAll(".legend")
.data(cScale.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + w + "," + (i * 20) + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", cScale);
legend.append("text")
.attr("y", 9)
.attr("x", -5)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
// Add expand button
if(filters.length > 0) {
svgContainer.append("g")
.attr("class", "legend expand")
.attr("transform", "translate(" + w + "," + ((cScale.domain().slice().reverse().length + 1) * 20) + ")")
.append("text")
.attr("y", 9)
.attr("x", -5)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text("DRILL IN!");
svgContainer.select(".expand")
.on("click", function() { updateViz(filters); });
}
};
var updateViz = function(filters) {
// Apply data filter
vizData = alzheimerData.filter(filters[0]);
filters = filters.slice(1);
// Select columns we'll need + initialise totals
vizKeys = d3.keys(vizData[0])
.filter(function(d) { return d.indexOf("Number of people with dementia") == 0; })
.map(function(d) { return { name: d, total: +0, year: d.slice(42,46) } });
var key = 1;
// Create column data
vizData.forEach(function(d) {
d3.keys(vizKeys).forEach(function(i) {
if (d3.keys(vizColumns).indexOf(vizKeys[i].name) > -1) {
vizColumns[vizKeys[i].name].push({
key: key,
region: d["Sub-Region"],
year: vizKeys[i].year,
y0: vizKeys[i].total,
y1: vizKeys[i].total += d[vizKeys[i].name]
});
} else {
vizColumns[vizKeys[i].name] = [{
key: key,
region: d["Sub-Region"],
year: vizKeys[i].year,
y0: vizKeys[i].total,
y1: vizKeys[i].total += d[vizKeys[i].name]
}];
};
key += 1;
});
});
var tmpVizColumns = [];
for (i=0; i < vizKeys.length; i++) {
tmpVizColumns = tmpVizColumns.concat(vizColumns[vizKeys[i].name]);
};
vizColumns = tmpVizColumns;
// Reset scales
regions = vizColumns.map(function(d) { return d.region })
.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
cScale = cScale.domain(regions)
.range(colours.slice(0,regions.length));
// Remove data
//svgContainer.selectAll("rect.barchart").remove();
// Create chart
var chartElements = svgContainer.selectAll("rect.barchart")
.data(vizColumns, function(d) {
return d.key;
});
chartElements.transition()
.duration(500)
.attr("class", "barchart")
.attr("x", function(d) { return xScale(d.year); } )
.attr("y", function(d) { return yScale(d.y1); } )
.attr("fill", function(d) { return cScale(d.region); } )
.attr("width", xScale.rangeBand())
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } );
var newChartElements = chartElements.enter()
.append("rect")
.attr("class", "barchart")
.attr("x", function(d) { return xScale(d.year); } )
.attr("y", function(d) { return yScale(d.y0); } )
.attr("fill", function(d) { return cScale(d.region); } )
.attr("width", xScale.rangeBand())
.attr("height", 0);
newChartElements.transition()
.delay(500)
.duration(500)
.attr("y", function(d) { return yScale(d.y1); } )
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); } );
// Legend
svgContainer.selectAll(".legend").remove();
var legend = svgContainer.selectAll(".legend")
.data(cScale.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + w + "," + (i * 20) + ")"; });
legend.append("rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", cScale);
legend.append("text")
.attr("y", 9)
.attr("x", -5)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
// Add expand button
if(filters.length > 0) {
svgContainer.append("g")
.attr("class", "legend expand")
.attr("transform", "translate(" + w + "," + ((cScale.domain().slice().reverse().length + 1) * 20) + ")")
.append("text")
.attr("y", 9)
.attr("x", -5)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text("DRILL IN!");
svgContainer.select(".expand")
.on("click", function() { updateViz(filters); });
}
};
<html>
<head>
<link rel="stylesheet" type="text/css" href="alzheimer.css">
<!-- Load d3.js -->
<script src="https://delormev.me/resources/d3/d3.min.js" charset="utf-8"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<div id="chart"></div>
<script src="alzheimer.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment