Skip to content

Instantly share code, notes, and snippets.

@BobHarper1
Forked from mbostock/.block
Last active July 21, 2016 15:45
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/06c153a070591e935bed772ab0d9de6e to your computer and use it in GitHub Desktop.
Save BobHarper1/06c153a070591e935bed772ab0d9de6e to your computer and use it in GitHub Desktop.
Northern Ireland Population Projection
license: gpl-3.0

This diagram shows the projected distribution of age groups in Northern Ireand in 5-year steps. Data from NISRA (2014-based Principal Population Projection measures).

Use the arrow keys to observe the changing population through the years.

The blue bars are the male population for each five-year age bracket, while the red bars show the female population. The bars are partially transparent so that you can see how they overlap, unlike the traditional side-by-side display which makes it difficult to compare the relative distribution of the sexes.

The earliest year of birth for each of the 5-year age groups are shown above the x-axis.

Thanks to D3's Mike Bostock for the original version.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 12px sans-serif;
font-weight: bold;
}
.y.axis path {
display: none;
}
.y.axis line {
stroke: #fff;
stroke-opacity: .2;
shape-rendering: crispEdges;
}
.y.axis .zero line {
stroke: #000;
stroke-opacity: 1;
}
.title {
font: 300 78px Helvetica Neue;
fill: #666;
}
.subtitle {
fill: #9E9E9E;
text-anchor: right;
}
.birthyear,
.age {
text-anchor: middle;
}
.birthyear {
fill: #fff;
font: 10px;
font-weight: normal;
}
rect {
fill-opacity: .6;
fill: #E91E63;
}
rect:first-child {
fill: #2196F3;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
function addCommas(nStr) {
nStr += '';
n = nStr.split('.');
x1 = n[0];
x2 = n.length > 1 ? '.' + n[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
var margin = {top: 20, right: 40, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
barWidth = Math.floor(width / 19) - 1;
var x = d3.scale.linear()
.range([barWidth / 2, width - barWidth / 2]);
var y = d3.scale.linear()
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("right")
.tickSize(-width)
// An SVG element with a bottom-right origin.
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 + ")");
// A sliding container to hold the bars by birthyear.
var birthyears = svg.append("g")
.attr("class", "birthyears");
// A label for the current year.
var title = svg.append("text")
.attr("class", "title")
.attr("dy", ".71em")
.attr("x", width - 200)
.text(2016);
d3.csv("population.csv", function(error, data) {
// Convert strings to numbers.
data.forEach(function(d) {
d.people = +d.people;
d.year = +d.year;
d.age = +d.age;
});
// Compute the extent of the data set in age and years.
var age1 = d3.max(data, function(d) { return d.age; }),
year0 = d3.min(data, function(d) { return d.year; }),
year1 = d3.max(data, function(d) { return d.year; }),
year = year0;
// Update the scale domains.
x.domain([year0, year0 - age1]);
y.domain([0, d3.max(data, function(d) { return d.people; })]);
var population = d3.nest()
.key(function(d) { return d.year; })
.rollup(function(v) { return {
male: d3.sum(v, function(d) { return (d.sex == 1) ? (d.people) : null ; } ),
female: d3.sum(v, function(d) { return (d.sex == 2) ? (d.people) : null ; } ),
total: d3.sum(v, function(d) { return d.people; })
}; })
.map(data);
console.log(population);
// Produce a map from year and birthyear to [male, female].
data = d3.nest()
.key(function(d) { return d.year; })
.key(function(d) { return d.year - d.age; })
.rollup(function(v) { return v.map(function(d) { return d.people; }); })
.map(data);
// Add an axis to show the population values.
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)")
.call(yAxis)
.selectAll("g")
.filter(function(value) { return !value; })
.classed("zero", true);
// Add labeled rects for each birthyear (so that no enter or exit is required).
var birthyear = birthyears.selectAll(".birthyear")
.data(d3.range(year0 - age1, year1 + 1, 5))
.enter().append("g")
.attr("class", "birthyear")
.attr("transform", function(birthyear) { return "translate(" + x(birthyear) + ",0)"; });
birthyear.selectAll("rect")
.data(function(birthyear) { return data[year][birthyear] || [0, 0]; })
.enter().append("rect")
.attr("x", -barWidth / 2)
.attr("width", barWidth)
.attr("y", y)
.attr("height", function(value) { return height - y(value); });
// Add labels to show birthyear.
birthyear.append("text")
.attr("y", height - 4)
.text(function(birthyear) { return birthyear; });
// Add labels to show age (separate; not animated).
svg.selectAll(".age")
.data(d3.range(0, age1 + 1, 5))
.enter().append("text")
.attr("class", "age")
.attr("x", function(age) { return x(year - age); })
.attr("y", height + 4)
.attr("dy", ".71em")
.text(function(age) { return (age === age1) ? (age1 + "+") : (age + "-" + (age + 5));});
// A label for the total population in the current year
var subtitle = svg.append("text")
.attr("class", "subtitle")
.attr("dy", ".50em")
.attr("x", width - 200)
.attr("y", 78)
.text("Total: " + addCommas(population[year].total));
// Allow the arrow keys to change the displayed year.
window.focus();
d3.select(window).on("keydown", function() {
switch (d3.event.keyCode) {
case 37: year = Math.max(year0, year - 5); break;
case 39: year = Math.min(year1, year + 5); break;
}
update();
});
function update() {
if (!(year in data)) return;
title.text(year);
if (year !== year0) {
subtitle.text("Total: " + addCommas(population[year].total) + " (5-year growth: " + addCommas(population[year].total - population[(year - 5)].total) + ")");
} else {
subtitle.text("Total: " + addCommas(population[year].total));
}
birthyears.transition()
.duration(750)
.attr("transform", "translate(" + (x(year0) - x(year)) + ",0)");
birthyear.selectAll("rect")
.data(function(birthyear) { return data[year][birthyear] || [0, 0]; })
.transition()
.duration(750)
.attr("y", y)
.attr("height", function(value) { return height - y(value); });
}
});
</script>
year age sex people
2016 0 1 63588
2016 0 2 60714
2016 5 1 65045
2016 5 2 62190
2016 10 1 58016
2016 10 2 55052
2016 15 1 61099
2016 15 2 58069
2016 20 1 61462
2016 20 2 58010
2016 25 1 62083
2016 25 2 62406
2016 30 1 60472
2016 30 2 62920
2016 35 1 57659
2016 35 2 61388
2016 40 1 58524
2016 40 2 61443
2016 45 1 63630
2016 45 2 66870
2016 50 1 64383
2016 50 2 66446
2016 55 1 56975
2016 55 2 58808
2016 60 1 48450
2016 60 2 48754
2016 65 1 43521
2016 65 2 46156
2016 70 1 36305
2016 70 2 40458
2016 75 1 25146
2016 75 2 30501
2016 80 1 16601
2016 80 2 23224
2016 85 1 8522
2016 85 2 15155
2016 90 1 2952
2016 90 2 6973
2016 95 1 561
2016 95 2 1810
2016 100 1 43
2016 100 2 231
2021 0 1 62521
2021 0 2 59634
2021 5 1 64250
2021 5 2 61444
2021 10 1 65537
2021 10 2 62739
2021 15 1 58384
2021 15 2 55494
2021 20 1 58911
2021 20 2 55605
2021 25 1 61948
2021 25 2 58771
2021 30 1 62021
2021 30 2 61818
2021 35 1 59837
2021 35 2 62226
2021 40 1 57076
2021 40 2 61092
2021 45 1 58061
2021 45 2 61233
2021 50 1 63008
2021 50 2 66492
2021 55 1 63212
2021 55 2 65725
2021 60 1 55246
2021 60 2 57663
2021 65 1 46045
2021 65 2 47199
2021 70 1 40047
2021 70 2 43671
2021 75 1 31436
2021 75 2 36744
2021 80 1 19650
2021 80 2 25492
2021 85 1 10753
2021 85 2 16553
2021 90 1 3920
2021 90 2 7987
2021 95 1 801
2021 95 2 2193
2021 100 1 73
2021 100 2 304
2026 0 1 60777
2026 0 2 57966
2026 5 1 63088
2026 5 2 60270
2026 10 1 64685
2026 10 2 61948
2026 15 1 65857
2026 15 2 63137
2026 20 1 56386
2026 20 2 53193
2026 25 1 59100
2026 25 2 56022
2026 30 1 61615
2026 30 2 57861
2026 35 1 61205
2026 35 2 60898
2026 40 1 59135
2026 40 2 61816
2026 45 1 56567
2026 45 2 60824
2026 50 1 57521
2026 50 2 60887
2026 55 1 61944
2026 55 2 65812
2026 60 1 61475
2026 60 2 64526
2026 65 1 52755
2026 65 2 55939
2026 70 1 42704
2026 70 2 44870
2026 75 1 35222
2026 75 2 39979
2026 80 1 25266
2026 80 2 31273
2026 85 1 13389
2026 85 2 18847
2026 90 1 5464
2026 90 2 9389
2026 95 1 1221
2026 95 2 2791
2026 100 1 117
2026 100 2 403
2031 0 1 58863
2031 0 2 56141
2031 5 1 61329
2031 5 2 58607
2031 10 1 63522
2031 10 2 60770
2031 15 1 64992
2031 15 2 62307
2031 20 1 63371
2031 20 2 60279
2031 25 1 56608
2031 25 2 53602
2031 30 1 58803
2031 30 2 55118
2031 35 1 60822
2031 35 2 56937
2031 40 1 60524
2031 40 2 60498
2031 45 1 58656
2031 45 2 61578
2031 50 1 56094
2031 50 2 60527
2031 55 1 56635
2031 55 2 60339
2031 60 1 60387
2031 60 2 64710
2031 65 1 58927
2031 65 2 62755
2031 70 1 49219
2031 70 2 53358
2031 75 1 37989
2031 75 2 41357
2031 80 1 28873
2031 80 2 34414
2031 85 1 17863
2031 85 2 23744
2031 90 1 7281
2031 90 2 11292
2031 95 1 1956
2031 95 2 3691
2031 100 1 223
2031 100 2 607
2036 0 1 58304
2036 0 2 55598
2036 5 1 59404
2036 5 2 56772
2036 10 1 61749
2036 10 2 59116
2036 15 1 63843
2036 15 2 61155
2036 20 1 62558
2036 20 2 59499
2036 25 1 63546
2036 25 2 60709
2036 30 1 56325
2036 30 2 52699
2036 35 1 58041
2036 35 2 54190
2036 40 1 60171
2036 40 2 56556
2036 45 1 60055
2036 45 2 60281
2036 50 1 58214
2036 50 2 61313
2036 55 1 55312
2036 55 2 60044
2036 60 1 55318
2036 60 2 59408
2036 65 1 58074
2036 65 2 63053
2036 70 1 55254
2036 70 2 60057
2036 75 1 44154
2036 75 2 49439
2036 80 1 31612
2036 80 2 35993
2036 85 1 20926
2036 85 2 26569
2036 90 1 10196
2036 90 2 14780
2036 95 1 2837
2036 95 2 4793
2036 100 1 435
2036 100 2 963
2041 0 1 59544
2041 0 2 56781
2041 5 1 58861
2041 5 2 56232
2041 10 1 59826
2041 10 2 57277
2041 15 1 62071
2041 15 2 59514
2041 20 1 61506
2041 20 2 58446
2041 25 1 62757
2041 25 2 59920
2041 30 1 63265
2041 30 2 59809
2041 35 1 55569
2041 35 2 51774
2041 40 1 57418
2041 40 2 53816
2041 45 1 59739
2041 45 2 56357
2041 50 1 59659
2041 50 2 60046
2041 55 1 57464
2041 55 2 60860
2041 60 1 54136
2041 60 2 59205
2041 65 1 53325
2041 65 2 57992
2041 70 1 54673
2041 70 2 60504
2041 75 1 49899
2041 75 2 55910
2041 80 1 37164
2041 80 2 43396
2041 85 1 23409
2041 85 2 28280
2041 90 1 12337
2041 90 2 16955
2041 95 1 4224
2041 95 2 6626
2041 100 1 717
2041 100 2 1416
2046 0 1 60684
2046 0 2 57870
2046 5 1 60103
2046 5 2 57415
2046 10 1 59279
2046 10 2 56733
2046 15 1 60158
2046 15 2 57685
2046 20 1 59855
2046 20 2 56913
2046 25 1 61723
2046 25 2 58875
2046 30 1 62491
2046 30 2 59030
2046 35 1 62528
2046 35 2 58909
2046 40 1 54978
2046 40 2 51401
2046 45 1 57040
2046 45 2 53629
2046 50 1 59375
2046 50 2 56165
2046 55 1 58947
2046 55 2 59642
2046 60 1 56317
2046 60 2 60069
2046 65 1 52322
2046 65 2 57904
2046 70 1 50368
2046 70 2 55784
2046 75 1 49659
2046 75 2 56548
2046 80 1 42419
2046 80 2 49441
2046 85 1 28003
2046 85 2 34589
2046 90 1 14254
2046 90 2 18587
2046 95 1 5350
2046 95 2 7912
2046 100 1 1168
2046 100 2 2139
2051 0 1 60246
2051 0 2 57452
2051 5 1 61252
2051 5 2 58505
2051 10 1 60527
2051 10 2 57918
2051 15 1 59620
2051 15 2 57145
2051 20 1 58064
2051 20 2 55224
2051 25 1 60100
2051 25 2 57344
2051 30 1 61460
2051 30 2 57995
2051 35 1 61769
2051 35 2 58137
2051 40 1 61934
2051 40 2 58552
2051 45 1 54624
2051 45 2 51223
2051 50 1 56729
2051 50 2 53475
2051 55 1 58720
2051 55 2 55839
2051 60 1 57858
2051 60 2 58931
2051 65 1 54547
2051 65 2 58829
2051 70 1 49615
2051 70 2 55848
2051 75 1 45990
2051 75 2 52327
2051 80 1 42586
2051 80 2 50335
2051 85 1 32465
2051 85 2 39899
2051 90 1 17545
2051 90 2 23294
2051 95 1 6503
2051 95 2 9107
2051 100 1 1633
2051 100 2 2799
2056 0 1 59040
2056 0 2 56300
2056 5 1 60817
2056 5 2 58099
2056 10 1 61679
2056 10 2 59011
2056 15 1 60871
2056 15 2 58330
2056 20 1 57599
2056 20 2 54748
2056 25 1 58328
2056 25 2 55650
2056 30 1 59853
2056 30 2 56461
2056 35 1 60738
2056 35 2 57103
2056 40 1 61183
2056 40 2 57780
2056 45 1 61579
2056 45 2 58396
2056 50 1 54348
2056 50 2 51096
2056 55 1 56146
2056 55 2 53205
2056 60 1 57710
2056 60 2 55222
2056 65 1 56159
2056 65 2 57792
2056 70 1 51893
2056 70 2 56864
2056 75 1 45604
2056 75 2 52627
2056 80 1 39781
2056 80 2 46874
2056 85 1 33056
2056 85 2 41086
2056 90 1 20869
2056 90 2 27450
2056 95 1 8369
2056 95 2 11895
2056 100 1 2174
2056 100 2 3524
2061 0 1 57945
2061 0 2 55254
2061 5 1 59602
2061 5 2 56955
2061 10 1 61250
2061 10 2 58603
2061 15 1 62015
2061 15 2 59421
2061 20 1 58795
2061 20 2 55864
2061 25 1 57892
2061 25 2 55176
2061 30 1 58099
2061 30 2 54768
2061 35 1 59151
2061 35 2 55564
2061 40 1 60177
2061 40 2 56759
2061 45 1 60857
2061 45 2 57629
2061 50 1 61308
2061 50 2 58263
2061 55 1 53831
2061 55 2 50883
2061 60 1 55249
2061 60 2 52667
2061 65 1 56126
2061 65 2 54222
2061 70 1 53600
2061 70 2 55983
2061 75 1 47934
2061 75 2 53758
2061 80 1 39851
2061 80 2 47509
2061 85 1 31302
2061 85 2 38674
2061 90 1 21746
2061 90 2 28822
2061 95 1 10362
2061 95 2 14533
2061 100 1 3019
2061 100 2 4901
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment