Last active
June 26, 2019 08:55
-
-
Save stuwilmur/6f9687b7e34efd7767f7d6e782b61437 to your computer and use it in GitHub Desktop.
gonorrhoea-statistics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HB16CD | HB16NM | OBJECTID | |
---|---|---|---|
S08000015 | Ayrshire and Arran | 0 | |
S08000016 | Borders | 1 | |
S08000017 | Dumfries and Galloway | 2 | |
S08000018 | Fife | 3 | |
S08000019 | Forth Valley | 4 | |
S08000020 | Grampian | 5 | |
S08000021 | Greater Glasgow and Clyde | 6 | |
S08000022 | Highland | 7 | |
S08000023 | Lanarkshire | 8 | |
S08000024 | Lothian | 9 | |
S08000025 | Orkney | 10 | |
S08000026 | Shetland | 11 | |
S08000027 | Tayside | 12 | |
S08000028 | Western Isles | 13 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Scotland gonorrhoea figures</title> | |
<meta charset="utf-8"> | |
<!-- Load d3.js --> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
<!-- Color Scale --> | |
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
<!-- Font --> | |
<link href="https://fonts.googleapis.com/css?family=Merriweather&display=swap" rel="stylesheet"> | |
<style> | |
body { | |
font-family: 'Merriweather', serif; | |
} | |
.yaxis { | |
font-family: 'Merriweather', serif; | |
} | |
.xaxis { | |
font-family: 'Merriweather', serif; | |
} | |
.ylabel { | |
font-size : 80%; | |
} | |
.caption { | |
font-size : 120%; | |
} | |
.subcaption { | |
font-size : 80%; | |
} | |
.notes { | |
font-size: 70%; | |
} | |
a { | |
text-decoration: none; | |
color : black; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
a:active { | |
color: black; | |
} | |
a:visited { | |
color: black; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Create a div where the graph will take place --> | |
<div id="my_dataviz"></div> | |
<p class="caption">Episodes of gonorrhoea in men and women in Scotland, by NHS board, 2013-2017</p> | |
<p class="subcaption">Figures from the <a href="https://hpsmicrosites.scot.nhs.uk/shbbv-framework-data-portal.aspx">Scottish Government's Sexual Health and Blood Borne Virus (SHBBV) open access Data Portal</a>.</p> | |
<p class="subcaption"> Map data originally from <a href = "https://data.gov.uk/dataset/27d0fe5f-79bb-4116-aec9-a8e565ff756a/nhs-health-boards">Scottish Government SpatialData.gov.scot</a>.</p> | |
<p class="subcaption">Includes all diagnoses i.e. genital, rectal, pharyngeal and conjunctival in those aged >10 years.</p> | |
<p class="notes">* An episode is defined as a six week period.</p> | |
<p class="notes">† Values < 5 have been masked in line with National Services Scotland's <a href="https://www.isdscotland.org/About-ISD/Confidentiality/">Statistical Disclosure Control Policy to prevent deductive disclosure</a>.</p> | |
<script> | |
var codesMap = new Map(); | |
// set the dimensions and margins of the graph | |
var margin = {top: 20, right: 100, bottom: 30, left: 70}, | |
width = 1200 - margin.left - margin.right, | |
height = 600 - margin.top - margin.bottom; | |
chartWidth = width / 2; | |
// append the svg object to the body of the page | |
var svg = d3.select("#my_dataviz") | |
.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 + ")"); | |
// create a tooltip | |
var Tooltip = d3.select("#my_dataviz") | |
.append("div") | |
.style("opacity", 0) | |
.attr("class", "tooltip") | |
.style("background-color", "white") | |
.style("border", "solid") | |
.style("border-width", "1px") | |
.style("border-radius", "0px") | |
.style("padding", "5px") | |
.style("position", "absolute") | |
.style("font-family", "Merriweather") | |
.style("font-size", "80%") | |
// create a tooltip for the map | |
var mapTooltip = d3.select("#my_dataviz") | |
.append("div") | |
.style("opacity", 0.1) | |
.attr("class", "tooltip") | |
.style("background-color", "white") | |
.style("border", "none") | |
.style("border-width", "1px") | |
.style("border-radius", "0px") | |
.style("padding", "5px") | |
.style("position", "absolute") | |
.style("font-family", "Merriweather") | |
.style("font-size", "80%") | |
// Three function that change the tooltip when user hover / move / leave a cell | |
var mouseover = function(d) { | |
Tooltip | |
.style("opacity", 1) | |
} | |
var mousemove = function(d) { | |
var output = d.value == -1 ? "no data†" : d.value | |
Tooltip | |
.html(d.gender + " " + d.year + ": " + output) | |
.style("left", (d3.mouse(this)[0]+70) + "px") | |
.style("top", (d3.mouse(this)[1]) + "px") | |
} | |
var mouseleave = function(d) { | |
Tooltip | |
.style("opacity", 0) | |
} | |
// Three function that change the map tooltip when user hover / move / leave a feature | |
var mapmouseover = function(d) { | |
mapTooltip | |
.style("opacity", 1) | |
d3.select(this) | |
.style('fill', colours.teal) | |
.style("opacity", d.properties.HBCode == selectedRegion ? 1 : 0.5) | |
} | |
var mapmousemove = function(d) { | |
mapTooltip | |
.html(codesMap.get(d.properties.HBCode)) | |
.style("left", (d3.mouse(this)[0] + 20) + "px") | |
.style("top", (d3.mouse(this)[1]) + "px") | |
} | |
var mapmouseleave = function(d) { | |
mapTooltip | |
.style("opacity", 0) | |
d3.select(this) | |
.style('fill', getRegionColour(d)) | |
.style("opacity", 1) | |
} | |
var mapmouseclick = function(d) { | |
selectedRegion = d.properties.HBCode; | |
optionsAndUpdate(); | |
updateRegionColours(); | |
} | |
var projection = d3.geoMercator() | |
.scale(2600) | |
.translate([width, height / 2]) | |
.center([-4, 58]); | |
var geoGenerator = d3.geoPath() | |
.projection(projection); | |
function getRegionColour(d) { | |
return d.properties.HBCode == selectedRegion ? colours.teal : colours.grey; | |
} | |
function updateGeo(geojson) { | |
var u = d3.select('svg') | |
.selectAll('path') | |
.data(geojson.features); | |
u.enter() | |
.append('path') | |
.attr("class", "region") | |
.attr('d', geoGenerator) | |
.style("fill", getRegionColour) | |
.on("mouseover", mapmouseover) | |
.on("mousemove", mapmousemove) | |
.on("mouseleave", mapmouseleave) | |
.on("click", mapmouseclick) | |
} | |
function updateRegionColours() | |
{ | |
var u = d3.select('svg') | |
.selectAll('path.region') | |
.transition() | |
.duration(500) | |
.style("opacity", 1) | |
.style("fill", getRegionColour); | |
} | |
var colours = { teal : "#69b3a2", grey : "#aaa", pink : "#b3669b" }; | |
var men_data; | |
var women_data; | |
var line; | |
var line_w; | |
var dot; | |
var dot_w; | |
var x; | |
var y; | |
var selectedRegion; | |
var yLabel; | |
var chartLabel; | |
var geojson; | |
var squareside = 18; | |
var theMax = 800; | |
var calc_max = false; | |
function optionsAndUpdate() | |
{ | |
// run the updateChart function with this selected option | |
update(selectedRegion) | |
} | |
// A function that updates the chart | |
function update(selectedGroup) { | |
// Create new data with the selection? | |
var theData = men_data ; | |
var dataFilter = theData.map(function(d){return {year: d.year, value:d[selectedGroup], gender : "men"} }) | |
var dataFilter_w = women_data.map(function(d){return {year: d.year, value:d[selectedGroup], gender : "women"} }) | |
var max_m = d3.max(dataFilter.map(function(d) {return +d.value;})); | |
var max_w = d3.max(dataFilter_w.map(function(d) {return +d.value;})); | |
var max = d3.max([max_w, max_m, 5]); | |
if (calc_max) { | |
theMax = max; | |
} | |
// Y axis | |
var y = d3.scaleLinear() | |
.domain( [0,theMax]) | |
.range([ height, 0 ]); | |
svg.select(".yaxis") | |
.transition() | |
.duration(1000) | |
.call(d3.axisLeft(y)); | |
// Give these new data to update line | |
line_w | |
.datum(dataFilter_w) | |
.transition() | |
.duration(1000) | |
.attr("d", d3.line() | |
.x(function(d) { return x(+d.year) }) | |
.y(function(d) { return y(+d.value) }) | |
) | |
dot_w | |
.data(dataFilter_w) | |
.transition() | |
.duration(1000) | |
.attr("x", function(d) { return x(+d.year) - squareside / 2 }) | |
.attr("y", function(d) { return y(+d.value) - squareside / 2}) | |
// Give these new data to update line | |
line | |
.datum(dataFilter) | |
.transition() | |
.duration(1000) | |
.attr("d", d3.line() | |
.x(function(d) { return x(+d.year) }) | |
.y(function(d) { return y(+d.value) }) | |
) | |
dot | |
.data(dataFilter) | |
.transition() | |
.duration(1000) | |
.attr("cx", function(d) { return x(+d.year) }) | |
.attr("cy", function(d) { return y(+d.value) }) | |
// update chart label | |
chartLabel | |
.transition() | |
.duration(500) | |
.style("opacity",0) | |
chartLabel | |
.transition() | |
.delay(500) | |
.duration(500) | |
.style("opacity",1) | |
.text(codesMap.get(selectedRegion)); | |
} | |
//Read the data | |
d3.csv('Health_Boards_May_2016_Names_and_Codes_in_Scotland.csv', function(lookup) | |
{ | |
lookup.reduce(function(map, obj) { | |
codesMap.set(obj.HB16CD, obj.HB16NM); | |
}, {}); | |
selectedRegion = lookup[0].HB16CD; | |
d3.json('sco_nhs_boards.geojson', function(err, json) { | |
d3.csv("sh-1_1_men.csv", function(m_data) { | |
d3.csv("sh-1_1_women.csv", function(w_data) { | |
geojson = json; | |
updateGeo(json); | |
men_data = m_data; | |
women_data = w_data; | |
// Create data usng initial selection | |
var theData = men_data; | |
var theData_w = women_data; | |
var theMax = 800; | |
var dataFilter = theData.map(function(d){return {year: d.year, value:d[selectedRegion], gender : "men"} }) | |
var dataFilter_w = women_data.map(function(d){return {year: d.year, value:d[selectedRegion], gender : "women"} }) | |
var max_m = d3.max(dataFilter.map(function(d) {return +d.value;})); | |
var max_w = d3.max(dataFilter_w.map(function(d) {return +d.value;})); | |
var max = d3.max([max_w, max_m, 5]); | |
if (calc_max) { | |
theMax = max; | |
} | |
// List of groups (here I have one group per column) | |
var allGroup = men_data.columns.slice(1) | |
// Add X axis --> it is a date format | |
x = d3.scaleLinear() | |
.domain([2013,2017]) | |
.range([ 0, chartWidth ]); | |
svg.append("g") | |
.attr("class", "xaxis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(d3.axisBottom(x).ticks(5).tickFormat(d3.format("d"))); | |
// Add Y axis | |
y = d3.scaleLinear() | |
.domain( [0,theMax]) | |
.range([ height, 0 ]); | |
svg.append("g") | |
.attr("class", "yaxis") | |
.call(d3.axisLeft(y)); | |
// Initialize line with group a | |
line_w = svg | |
.append('g') | |
.append("path") | |
.datum(dataFilter_w) | |
.attr("d", d3.line() | |
.x(function(d) { return x(+d.year) }) | |
.y(function(d) { return y(+d.value) }) | |
) | |
.attr("stroke", "black") | |
.style("stroke-width", 4) | |
.style("fill", "none") | |
// Initialize dots with group a | |
dot_w = svg | |
.selectAll('rect.w') | |
.data(dataFilter_w) | |
.enter() | |
.append('rect') | |
.attr("class", "w") | |
.attr("x", function(d) { return x(+d.year) - squareside / 2 }) | |
.attr("y", function(d) { return y(+d.value) - squareside / 2}) | |
.attr("width", squareside) | |
.attr("height", squareside) | |
.style("fill", colours.teal) | |
.on("mouseover", mouseover) | |
.on("mousemove", mousemove) | |
.on("mouseleave", mouseleave) | |
// Initialize line with group a | |
line = svg | |
.append('g') | |
.append("path") | |
.datum(dataFilter) | |
.attr("d", d3.line() | |
.x(function(d) { return x(+d.year) }) | |
.y(function(d) { return y(+d.value) }) | |
) | |
.attr("stroke", "black") | |
.style("stroke-width", 4) | |
.style("fill", "none") | |
// Initialize dots with group a | |
dot = svg | |
.selectAll('circle.m') | |
.data(dataFilter) | |
.enter() | |
.append('circle') | |
.attr("class", "m") | |
.attr("cx", function(d) { return x(+d.year) }) | |
.attr("cy", function(d) { return y(+d.value) }) | |
.attr("r", 7) | |
.style("fill", colours.pink) | |
.on("mouseover", mouseover) | |
.on("mousemove", mousemove) | |
.on("mouseleave", mouseleave) | |
ylabel = svg | |
.append("text") | |
.attr("class", "ylabel") | |
.attr("text-anchor", "end") | |
.attr("y", -margin.left) | |
.attr("dy", ".75em") | |
.attr("transform", "rotate(-90)") | |
.text("Episodes of gonorrhoea*"); | |
chartLabel = svg | |
.append("text") | |
.attr("class", "chartlabel") | |
.attr("y", 0) | |
.attr("dy", ".75em") | |
.attr("x", 0) | |
.attr("dx", "1em") | |
.text(codesMap.get(selectedRegion)); | |
}) | |
}) | |
}) | |
}) | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MIT License | |
Copyright (c) 2019 stuwilmur | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
SOFTWARE. |
View raw
(Sorry about that, but we can’t show files that are this big right now.)
View raw
(Sorry about that, but we can’t show files that are this big right now.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment