Skip to content

Instantly share code, notes, and snippets.

@BobHarper1
Last active August 23, 2017 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BobHarper1/0d90e0016bc5bff0ba016a510ef88f82 to your computer and use it in GitHub Desktop.
Save BobHarper1/0d90e0016bc5bff0ba016a510ef88f82 to your computer and use it in GitHub Desktop.
Life Expectancy Decomposition Gap. Most and Least Deprived.

A recreation of the waterfall chart example in Wikipedia. This type of chart is popularized by McKinsey & Company in explaining the cumulative impact of various factors on some quantitative value.

category name value
Circulatory CHD 0.5
Circulatory Stroke 0.1
Circulatory Other Circulatory 0.2
Respiratory Pneumonia 0.1
Respiratory Chronic Lower Respiratory Disease 0.5
Respiratory Other Respiratory 0.1
Cancer Lung 0.5
Cancer Breast 0.0
Cancer Prostate 0.0
Cancer Colorectal 0.0
Cancer Lymphatic 0.0
Cancer Pancreatic 0.0
Cancer Other Cancer 0.3
Metabolic Diabetes Mellitus 0.1
Metabolic Other Metabolic 0.0
Mental Mental /Behavioural 0.0
Nervous Nervous System -0.1
Digestive Chronic Liver Disease 0.0
Digestive Other Digestive 0.1
Accidental Car Accidents 0.0
Accidental Other Accidents 0.0
Suicide Suicide 0.0
Genitourinary Kidney Disease 0.1
Genitourinary Other Genitourinary 0.0
Maternal & Infant Perinatal 0.0
Maternal & Infant Congenital 0.0
Other Other Causes 0.0
category name value
Circulatory CHD 0.4309176
Circulatory Stroke 0.1447718
Circulatory Other Circulatory 0.2789977
Respiratory Pneumonia 0.1013657
Respiratory Chronic Lower Respiratory Disease 0.5857965
Respiratory Other Respiratory 0.0600080
Cancer Lung 0.8408953
Cancer Breast 0.0033268
Cancer Prostate 0.0000000
Cancer Colorectal 0.0172606
Cancer Lymphatic -0.0091367
Cancer Pancreatic 0.0541023
Cancer Other Cancer 0.5900032
Metabolic Diabetes Mellitus 0.0773707
Metabolic Other Metabolic 0.0588363
Mental Mental /Behavioural -0.0769478
Nervous Nervous System -0.0448543
Digestive Chronic Liver Disease 0.3090852
Digestive Other Digestive 0.2922359
Accidental Car Accidents 0.0369375
Accidental Other Accidents 0.1198048
Suicide Suicide 0.2515307
Genitourinary Kidney Disease 0.0261426
Genitourinary Other Genitourinary -0.0017711
Maternal & Infant Perinatal 0.0888981
Maternal & Infant Congenital -0.1083844
Other Other Causes 0.1237873
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:500" rel="stylesheet">
</head>
<style>
html,
body {
font-family: 'Roboto', sans-serif;
}
svg {
shape-rendering: crispedges;
}
.bar.positive rect {
fill: #ed143d;
}
.bar.negative rect {
fill: #4445bf;
}
.bar line.connector {
stroke: #000000;
stroke-dasharray: 1;
}
.bar text {
fill: white;
font: 12px;
text-anchor: middle;
}
.axis text {
font: 12px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.d3-tip {
line-height: 1;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip.cause:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
.d3-tip.cause.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.tooltip.positive {
color: #fb6498;
}
.tooltip.negative {
color: #00bcd4;
}
</style>
<h1>Life Expectancy Gap: Attributable to Underlying Causes of Death</h1>
<h2>Difference between most and least deprived areas, 2010-12</h2>
<p>
<select id="opts">
<option value="male_birth" selected="selected">Male, at birth</option>
<option value="female_birth">Female, at birth</option>
<option value="male_65">Male, 65 years</option>
<option value="female_65">Female, 65 years</option>
</select>
Least Deprived Life Expectancy: <span id="least"></span> / Most Deprived Life Expectancy: <span id="most"></span> / <span style="color: red">Gap: <span id="gap"></span> years</span>
</p>
<svg class="chart"></svg>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var chart = function(dataset) {
var margin = {
top: 20,
right: 30,
bottom: 150,
left: 40
},
width = 1300 - margin.left - margin.right,
height = 800 - margin.top - margin.bottom,
padding = 0.3,
connector = 5;
var expectancies = {
"male_birth": {
"most_deprived": 73.5,
"least_deprived": 80.7,
"gap": 7.3
},
"female_birth": {
"most_deprived": 79.6,
"least_deprived": 83.8,
"gap": 4.3
},
"male_65": {
"most_deprived": 16.1,
"least_deprived": 19.3,
"gap": 3.2
},
"female_65": {
"most_deprived": 18.8,
"least_deprived": 21.5,
"gap": 2.7
}
}
var categories = [{
"category": "Circulatory",
"colour": "ffed6f"
},
{
"category": "Respiratory",
"colour": "#8dd3c7"
},
{
"category": "Cancer",
"colour": "#ffffb3"
},
{
"category": "Metabolic",
"colour": "#bebada"
},
{
"category": "Mental",
"colour": "#fb8072"
},
{
"category": "Nervous",
"colour": "#80b1d3"
},
{
"category": "Digestive",
"colour": "#fdb462"
},
{
"category": "Accidental",
"colour": "#b3de69"
},
{
"category": "Suicide",
"colour": "#fccde5"
},
{
"category": "Genitourinary",
"colour": "#d9d9d9"
},
{
"category": "Maternal & Infant",
"colour": "#bc80bd"
},
{
"category": "Other",
"colour": "#ccebc5"
},
{
"category": "Total",
"colour": "#ffffff"
}
];
for (var i = 0; i < categories.length; i++) {
categories[i].difference = 0
}
var a = d3.scale.ordinal()
.rangeRoundBands([0, width])
.domain(categories.map(function(a) {
return a.category;
}));
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], padding);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis1 = d3.svg.axis()
.scale(x)
.tickPadding(x.width)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(function(d) {
return "-" + d;
});
var chart = d3.select(".chart")
.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(dataset + '.csv', type, function(error, data) {
// Transform data (i.e., finding cumulative values and total) for easier charting
var cumulative = 0;
for (var i = 0; i < data.length; i++) {
data[i].start = cumulative;
cumulative += data[i].value;
data[i].end = cumulative;
for (var j = 0; j < categories.length; j++) {
if (categories[j].category === data[i].category) {
categories[j].difference += data[i].value;
}
if (categories[j].category === "Total") {
categories[j].difference === cumulative;
}
categories[j].class = (categories[j].difference >= 0) ? 'positive' : 'negative';
categories[j].tooltip = "Group: " + categories[j].category + "<br />Total difference: " + "<span class='tooltip " + categories[j].class + "'>" + categories[j].difference.toFixed(2) * -1 + " years</span>";
}
data[i].class = (data[i].value >= 0) ? 'positive' : 'negative';
data[i].tooltip = data[i].name + ": <br /><span class='tooltip " + data[i].class + "'>" + data[i].value.toFixed(2) * -1 + " years</span>";
}
data.push({
name: 'Total difference',
end: cumulative,
start: 0,
class: 'total ' + (cumulative >= 0) ? 'positive' : 'negative',
category: 'Total',
tooltip: "Total difference:<br /><span class='tooltip " + ((cumulative >= 0) ? 'positive' : 'negative') + "'>" + cumulative.toFixed(2) * -1 + " years</span>"
});
x.domain(data.map(function(d) {
return d.name;
}));
y.domain([0, d3.max(data, function(d) {
return Math.ceil(d.end);
})]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis1)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".3em")
.attr("transform", "rotate(-90)");
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
var cause_tip = d3.tip()
.attr('class', 'd3-tip cause')
.offset([-10, 0])
.html(function(d) {
return d.tooltip;
});
var category_tip = d3.tip()
.attr('class', 'd3-tip')
.offset([70, 0])
.html(function(d) {
for (c = 0; c < categories.length; c++) {
if (categories[c].category === d.category) {
return categories[c].tooltip
}
}
});
var bar = chart.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", function(d) {
return "bar " + d.class
})
.attr("transform", function(d) {
return "translate(" + x(d.name) + ",0)";
});
bar.call(cause_tip).call(category_tip);
bar.append("rect")
.attr("height", height)
// .attr("width", a.rangeBand() / 2 + connector + connector - padding)
.attr("width", x.rangeBand() / (1 - padding) - padding)
.style("fill", function(d) {
for (i = 0; i < categories.length; i++) {
if (categories[i].category === d.category) {
return (categories[i].colour);
}
}
})
.style("opacity", .5)
.on("mouseover", category_tip.show)
.on("mouseout", category_tip.hide);
bar.append("rect")
.attr("y", function(d) {
return y(Math.max(d.start, d.end));
})
.attr("height", function(d) {
return Math.abs(y(d.start) - y(d.end));
})
.attr("width", x.rangeBand())
.on("mouseover", cause_tip.show)
.on("mouseout", cause_tip.hide);
// bar.append("text")
// .attr("x", x.rangeBand() / 2)
// .attr("y", function(d) {
// return y(d.end) + 5;
// })
// .attr("dy", function(d) {
// return ((d.class == 'positive') ? '-' : '') + ".75em"
// })
// .text(function(d) {
// return ((d.class == 'positive') ? "-" + (d.end - d.start).toFixed(2) : (d.end - d.start).toFixed(2) * -1);
// });
bar.filter(function(d) {
return d.class != "total"
}).append("line")
.attr("class", "connector")
.attr("x1", x.rangeBand())
.attr("y1", function(d) {
return y(d.end)
})
.attr("x2", x.rangeBand() / (1 - padding))
.attr("y2", function(d) {
return y(d.end)
});
});
function type(d) {
d.value = +d.value;
return d;
}
d3.select("#least")
.text(expectancies[dataset].least_deprived);
d3.select("#most")
.text(expectancies[dataset].most_deprived);
d3.select("#gap")
.text(expectancies[dataset].gap);
}
var clearChart = function() {
d3.selectAll("svg > *").remove();
}
chart('male_birth');
d3.select('#opts')
.on('change', function() {
var newData = d3.select(this).property('value');
clearChart();
chart(newData);
});
</script>
category name value
Circulatory CHD 0.7
Circulatory Stroke 0.2
Circulatory Other Circulatory 0.2
Respiratory Pneumonia 0.0
Respiratory Chronic Lower Respiratory Disease 0.5
Respiratory Other Respiratory 0.1
Cancer Lung 0.7
Cancer Breast 0.0
Cancer Prostate 0.1
Cancer Colorectal 0.1
Cancer Lymphatic 0.0
Cancer Pancreatic 0.0
Cancer Other Cancer 0.3
Metabolic Diabetes Mellitus 0.0
Metabolic Other Metabolic 0.0
Mental Mental /Behavioural 0.0
Nervous Nervous System 0.0
Digestive Chronic Liver Disease 0.1
Digestive Other Digestive 0.1
Accidental Car Accidents 0.0
Accidental Other Accidents 0.0
Suicide Suicide 0.0
Genitourinary Kidney Disease 0.0
Genitourinary Other Genitourinary 0.0
Maternal & Infant Perinatal 0.0
Maternal & Infant Congenital 0.0
Other Other Causes 0.0
category name value
Circulatory CHD 1.117086595
Circulatory Stroke 0.234785746
Circulatory Other Circulatory 0.358991482
Respiratory Pneumonia 0.126408188
Respiratory Chronic Lower Respiratory Disease 0.448586187
Respiratory Other Respiratory 0.139638181
Cancer Lung 0.852730836
Cancer Breast -0.004541523
Cancer Prostate -0.02049647
Cancer Colorectal 0.127236545
Cancer Lymphatic 0.028300365
Cancer Pancreatic 0.05226907
Cancer Other Cancer 0.568443925
Metabolic Diabetes Mellitus 0.13439617
Metabolic Other Metabolic -0.012405414
Mental Mental /Behavioural 0.262635578
Nervous Nervous System -0.011404273
Digestive Chronic Liver Disease 0.51106605
Digestive Other Digestive 0.188735921
Accidental Car Accidents 0.131103431
Accidental Other Accidents 0.525996497
Suicide Suicide 1.101275991
Genitourinary Kidney Disease 0.013654622
Genitourinary Other Genitourinary 0.028265026
Maternal & Infant Perinatal 0.083183118
Maternal & Infant Congenital 0.021763052
Other Other Causes 0.256742178
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment