Skip to content

Instantly share code, notes, and snippets.

@BobHarper1
Last active August 23, 2017 16:00
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/cb6583bb0c21aaa3166dd373504493e3 to your computer and use it in GitHub Desktop.
Save BobHarper1/cb6583bb0c21aaa3166dd373504493e3 to your computer and use it in GitHub Desktop.
Life Expectancy Decomposition Gap. England and Northern Ireland.

Comparison of causes of death contributing to the average life expectancy gap between England and Northern Ireland. Differences can go up as well as down.

Select measure (male / female, at birth / age 65) using the drop down. Attributable causes of death are categorised (e.g. Respiratory, Cancer etc.)

Move cursor over waterfall bars for contributing values, and over background colours for the total decomposition of that group.

Source: Department of Health, HSC Inequalities Monitoring System. http://data.nicva.org/dataset/life-expectancy-decomposition

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.1
Circulatory Stroke 0.1
Circulatory Other Circulatory -0.1
Respiratory Pneumonia 0.1
Respiratory Chronic Lower Respiratory Disease 0.0
Respiratory Other Respiratory 0.0
Cancer Lung 0.0
Cancer Breast 0.0
Cancer Prostate 0.0
Cancer Colorectal 0.0
Cancer Lymphatic 0.0
Cancer Pancreatic 0.0
Cancer Other Cancer 0.0
Metabolic Diabetes Mellitus 0.0
Metabolic Other Metabolic 0.0
Mental Mental /Behavioural 0.1
Nervous Nervous System 0.1
Digestive Chronic Liver Disease 0.0
Digestive Other Digestive 0.0
Accidental Car Accidents 0.0
Accidental Other Accidents 0.1
Suicide Suicide 0.1
Genitourinary Kidney Disease 0.1
Genitourinary Other Genitourinary 0.0
Maternal & Infant Perinatal 0.2
Maternal & Infant Congenital 0.1
Other Other Causes -0.3
<!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 England and Northern Ireland, 2010-12</h2>
<p>
Select: <select id="opts">
<option value="male_birth" selected="selected">Male, at birth</option>
<option value="female_birth">Female, at birth</option>
</select>
NI Life Expectancy: <span id="ni"></span> / England Life Expectancy: <span id="end"></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 = 1020 - margin.left - margin.right,
height = 700 - margin.top - margin.bottom,
padding = 0.3,
connector = 5;
var expectancies = {
"male_birth": {
"ni": 77.7,
"england": 79,
"gap": 1.4
},
"female_birth": {
"ni": 82.1,
"england": 82.8,
"gap": 0.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("#ni")
.text(expectancies[dataset].ni);
d3.select("#end")
.text(expectancies[dataset].eng);
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.3
Circulatory Stroke 0.1
Circulatory Other Circulatory -0.1
Respiratory Pneumonia 0.0
Respiratory Chronic Lower Respiratory Disease 0.0
Respiratory Other Respiratory 0.0
Cancer Lung 0.1
Cancer Breast 0.0
Cancer Prostate 0.0
Cancer Colorectal 0.0
Cancer Lymphatic 0.0
Cancer Pancreatic 0.0
Cancer Other Cancer 0.0
Metabolic Diabetes Mellitus 0.1
Metabolic Other Metabolic 0.0
Mental Mental /Behavioural 0.1
Nervous Nervous System 0.1
Digestive Chronic Liver Disease 0.0
Digestive Other Digestive 0.0
Accidental Car Accidents 0.1
Accidental Other Accidents 0.2
Suicide Suicide 0.4
Genitourinary Kidney Disease 0.0
Genitourinary Other Genitourinary 0.0
Maternal & Infant Perinatal 0.2
Maternal & Infant Congenital 0.1
Other Other Causes -0.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment