Last active
November 13, 2015 18:49
-
-
Save stormpython/bebb2a4e85a7bf21cde7 to your computer and use it in GitHub Desktop.
European Life Expectancy
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
[ | |
{ "abbr": "ad", "name": "Andorra", "leb": 84.2, "pop": 79200, "size": 468 }, | |
{ "abbr": "al", "name": "Albania", "leb": 74, "pop": 2887000, "size": 28748 }, | |
{ "abbr": "at", "name": "Austria", "leb": 81.5, "pop": 8608000, "size": 83858 }, | |
{ "abbr": "ba", "name": "Bosnia and Herzegovina", "leb": 76, "pop": 3750000, "size": 51129 }, | |
{ "abbr": "be", "name": "Belgium", "leb": 81, "pop": 11259000, "size": 30510 }, | |
{ "abbr": "bg", "name": "Bulgaria", "leb": 74.5, "pop": 7265000, "size": 110910 }, | |
{ "abbr": "by", "name": "Belaurs", "leb": 72.5, "pop": 9481000, "size": 207600 }, | |
{ "abbr": "ch", "name": "Switzerland", "leb": 82.8, "pop": 8081000, "size": 41290 }, | |
{ "abbr": "cy", "name": "Cyprus", "leb": 81.2, "pop": 876000, "size": 9251 }, | |
{ "abbr": "cz", "name": "Czech Republic", "leb": 78, "pop": 10535000, "size": 78866 }, | |
{ "abbr": "de", "name": "Germany", "leb": 81, "pop": 80620000, "size": 357050 }, | |
{ "abbr": "dk", "name": "Denmark", "leb": 79.5, "pop": 5614000, "size": 43094 }, | |
{ "abbr": "ee", "name": "Estonia", "leb": 76.1, "pop": 1315000, "size": 45226 }, | |
{ "abbr": "es", "name": "Spain", "leb": 82.5, "pop": 46335000, "size": 505992 }, | |
{ "abbr": "fi", "name": "Finland", "leb": 81, "pop": 5439000, "size": 338145 }, | |
{ "abbr": "fo", "name": "Faeroe Islands", "leb": 79.9, "pop": 49500, "size": 1399 }, | |
{ "abbr": "fr", "name": "France", "leb": 81.5, "pop": 64304000, "size": 671308 }, | |
{ "abbr": "ge", "name": "Georgia", "leb": 74.5, "pop": 3707000, "size": 2000 }, | |
{ "abbr": "gg", "name": "Guernsey", "leb": 82, "pop": 65400, "size": 78 }, | |
{ "abbr": "gr", "name": "Greece", "leb": 81, "pop": 10769000, "size": 131940 }, | |
{ "abbr": "hr", "name": "Croatia", "leb": 77.5, "pop": 4230000, "size": 56542 }, | |
{ "abbr": "hu", "name": "Hungary", "leb": 75, "pop": 9835000, "size": 93030 }, | |
{ "abbr": "ie", "name": "Ireland", "leb": 81.4, "pop": 4630000, "size": 70280 }, | |
{ "abbr": "im", "name": "Isle of Man", "leb": 80.8, "pop": 89000, "size": 572 }, | |
{ "abbr": "is", "name": "Iceland", "leb": 83.3, "pop": 331000, "size": 103000 }, | |
{ "abbr": "it", "name": "Italy", "leb": 83.1, "pop": 60963000, "size": 301318 }, | |
{ "abbr": "je", "name": "Jersey", "leb": 78.5, "pop": 103000, "size": 120 }, | |
{ "abbr": "li", "name": "Liechtenstein", "leb": 80.7, "pop": 37000, "size": 160 }, | |
{ "abbr": "lt", "name": "Lithuania", "leb": 75.9, "pop": 2906000, "size": 65200 }, | |
{ "abbr": "lu", "name": "Luxembourg", "leb": 82, "pop": 570000, "size": 2586 }, | |
{ "abbr": "lv", "name": "Latvia", "leb": 74.5, "pop": 1979000, "size": 64589 }, | |
{ "abbr": "mc", "name": "Monaco", "leb": 89.6, "pop": 37000, "size": 1.95 }, | |
{ "abbr": "md", "name": "Moldova", "leb": 71, "pop": 3564000, "size": 33843 }, | |
{ "abbr": "me", "name": "Montenegro", "leb": 74.5, "pop": 620000, "size": 13812 }, | |
{ "abbr": "mk", "name": "Macedonia", "leb": 75, "pop": 2071000, "size": 25713 }, | |
{ "abbr": "mt", "name": "Malta", "leb": 81, "pop": 425000, "size": 316 }, | |
{ "abbr": "nl", "name": "Netherlands", "leb": 81.5, "pop": 16933000, "size": 41526 }, | |
{ "abbr": "no", "name": "Norway", "leb": 81.9, "pop": 5194000, "size": 385155 }, | |
{ "abbr": "pl", "name": "Poland", "leb": 77.5, "pop": 38494000, "size": 312685 }, | |
{ "abbr": "pt", "name": "Portugal", "leb": 80, "pop": 10311000, "size": 91568 }, | |
{ "abbr": "ro", "name": "Romania", "leb": 74, "pop": 19822000, "size": 238392 }, | |
{ "abbr": "rs", "name": "Serbia", "leb": 74, "pop": 7164000, "size": 88361 }, | |
{ "abbr": "ru", "name": "Russia", "leb": 70.5, "pop": 143500000, "size": 3836652 }, | |
{ "abbr": "se", "name": "Sweden", "leb": 83, "pop": 9794000, "size": 449964 }, | |
{ "abbr": "si", "name": "Slovenia", "leb": 80, "pop": 2065000, "size": 20273 }, | |
{ "abbr": "sk", "name": "Slovakia", "leb": 76.3, "pop": 5414000, "size": 48845 }, | |
{ "abbr": "sm", "name": "San Marino", "leb": 83.5, "pop": 33000, "size": 61 }, | |
{ "abbr": "tr", "name": "Turkey", "leb": 74.4, "pop": 74930000, "size": 807462 }, | |
{ "abbr": "ua", "name": "Ukraine", "leb": 68, "pop": 42850000, "size": 603628 }, | |
{ "abbr": "uk", "name": "United Kingdom", "leb": 81, "pop": 64915000, "size": 244820 }, | |
{ "abbr": "va", "name": "Vatican City", "leb": 0, "pop": 800, "size": 0.44 } | |
] |
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> | |
<meta charset="utf-8"> | |
<title></title> | |
<link rel="stylesheet" type="text/css" href="https://googledrive.com/host/0B1EG_orcd43bcWdLUkVDMHNxbWM/css/continental.css"> | |
<style> | |
body { | |
background-color: #f0f0f0; | |
} | |
#map { | |
position: relative; | |
font-size: 200px; | |
margin-left: 650px; | |
} | |
.moused { | |
opacity: 1 !important; | |
} | |
#map > [class*="map-"] { | |
position: absolute; | |
border: white; | |
top: 0; | |
left: 0; | |
color: silver; | |
} | |
body { | |
fill: #444; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: grey; | |
shape-rendering: crispEdges; | |
} | |
.hover { | |
background-color: #eee; | |
} | |
#tooltip { | |
position: absolute; | |
width: auto; | |
height: auto; | |
padding: 10px; | |
background-color: white; | |
-webkit-border-radius: 10px; | |
-moz-border-radius: 10px; | |
border-radius: 10px; | |
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); | |
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); | |
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); | |
pointer-events: none; | |
} | |
#tooltip.hidden { | |
display: none; | |
} | |
#tooltip p { | |
margin: 0; | |
font-family: sans-serif; | |
font-size: 16px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<div id="chart"></div> | |
<div id="tooltip" class="hidden"> | |
<p><span id="value"></span></p> | |
</div> | |
</body> | |
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="scatterplot.js" charset="utf-8"></script> | |
<script> | |
/* | |
* European country data collected from Wikipedia sources. | |
* abbr - country abbrevation | |
* name - country name | |
* leb - life expectancy at birth | |
* pop - population | |
* size - area km^2 | |
*/ | |
d3.json("countries.json", function (error, countries) { | |
if (error) throw error; | |
countries = countries.filter(function (country) { | |
return country.abbr !== "va"; // Exclude Vatican City - does not have a leb | |
}); | |
countries.forEach(function (country) { | |
country.den = country.pop / country.size; // Add population density measure | |
}); | |
// Color scale for life expectancy at birth | |
var colorAccessor = function (d) { return d.leb; }; | |
var radiusAccessor = function (d) { return Math.log(d.size); }; | |
var colorScale = d3.scale.log() | |
.domain(d3.extent(countries, colorAccessor)) | |
.range(["red", "blue"]); | |
// Create scatterplot function | |
var chart = scatterPlot() | |
.width(720) | |
.x(function (d) { return d.leb; }) | |
.y(function (d) { return d.pop; }) | |
.circleClass(function (d) { return d.abbr; }) | |
.radius(radiusAccessor) | |
.color(colorScale) | |
.fill(colorAccessor) | |
.opacity(0.5) | |
.axisX({ title: "Median Life Expectancy at Birth" }) | |
.axisY({ title: "Population Size" }) | |
.on("mouseover", function (d, i) { | |
// Increase size of circle | |
d3.select(this).classed("moused", true).transition().attr("r", 20); | |
d3.select("tr." + d.abbr).classed("hover", true); | |
// Grey out all countries except one selected | |
d3.selectAll("span[class^='map-']") | |
.filter(function (e) { return e.abbr !== d.abbr; }) | |
.style("color", "grey"); | |
// Tooltip | |
var xPosition = parseFloat(d3.select(this).attr("cx")); | |
var yPosition; | |
if (d3.select(this).attr("cy") < 140) { | |
yPosition = parseFloat(d3.select(this).attr("cy")) + 50; | |
} else { | |
yPosition = parseFloat(d3.select(this).attr("cy")) - 100; | |
} | |
d3.select("#tooltip") | |
.style("left", xPosition + "px") | |
.style("top", yPosition + "px") | |
.select("#value") | |
.html( | |
"Country: " + d.name + | |
"<br>Population: " + numberWithCommas(d.pop) + | |
"<br>Median Life Expectancy: " + d.leb + | |
"<br>Country Area: " + numberWithCommas(d.size) | |
); | |
d3.select("#tooltip").classed("hidden", false); | |
}) | |
.on("mouseout", function (d, i) { | |
// Return circles to original size | |
d3.select(this).classed("moused", false) | |
.transition().attr("r", radiusAccessor); | |
d3.select("tr." + d.abbr).classed("hover", false); | |
// Re-color countries | |
d3.selectAll("span[class^='map-']") | |
.style("color", function (d) { return colorScale(d.leb); }); | |
// Hide tooltip | |
d3.select("#tooltip").classed("hidden", true); | |
}); | |
// Create map | |
var map = d3.select("#map"); | |
var span = map.selectAll("span") | |
.data(countries) | |
.enter().append("span") | |
.attr("class", function (d) { | |
return "map-" + d.abbr; | |
}) | |
.style("color", function (d) { | |
return colorScale(d.leb); | |
}); | |
d3.select("#chart") | |
.datum(countries) | |
.call(chart); | |
function numberWithCommas(x) { | |
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | |
} | |
}); | |
</script> | |
</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
function scatterPlot() { | |
// Private variables | |
var margin = { top: 20, right: 20, bottom: 50, left: 100 }; | |
var width = 960 - margin.left - margin.right; | |
var height = 500 - margin.top - margin.bottom; | |
var color = d3.scale.category20(); | |
var dispatch = d3.dispatch("mouseover", "mouseout"); | |
var x = function (d) { return d.x; }; | |
var y = function (d) { return d.y; }; | |
var radius = function (d) { return d.radius; }; | |
var fill = function (d) { return d.color; }; | |
var stroke = function (d) { return color(d.color); }; | |
var strokeWidth = 0; | |
var opacity = 1; | |
var circleClass = "circle"; | |
var xScale = d3.scale.linear(); | |
var yScale = d3.scale.log(); | |
var xAxis = d3.svg.axis().orient("bottom"); | |
var yAxis = d3.svg.axis().orient("left"); | |
var axisX = { | |
axisClass: "x axis", | |
titleClass: "x-label", | |
x: function () { return width / 2; }, | |
y: 30, | |
dy: ".71em", | |
textAnchor: "middle", | |
title: "" | |
}; | |
var axisY = { | |
axisClass: "y axis", | |
titleClass: "y-label", | |
x: function () { return -height / 2; }, | |
y: -60, | |
dy: ".71em", | |
textAnchor: "middle", | |
title: "" | |
}; | |
function chart(selection) { | |
selection.each(function (data, index) { | |
// Re-define data. Do not alter original dataset | |
data.forEach(function (d, i) { | |
d.x = x.call(data, d, i); | |
d.y = y.call(data, d, i); | |
d.radius = radius.call(data, d, i); | |
d.color = fill.call(data, d, i); | |
}); | |
var svg = d3.select("#chart").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 + ")"); | |
xScale | |
.domain(d3.extent(data, function (d) { return d.x; })) | |
.range([0, width]) | |
.nice(); | |
yScale | |
.domain(d3.extent(data, function (d) { return d.y; })) | |
.range([height, 0]) | |
.nice(); | |
// Creating the x axis. | |
svg.append("g") | |
.attr("class", axisX.axisClass) | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis.scale(xScale)) | |
.append("text") | |
.attr("class", axisX.titleClass) | |
.attr("x", axisX.x) | |
.attr("y", axisX.y) | |
.attr("dy", axisX.dy) | |
.style("text-anchor", axisX.textAnchor) | |
.text(axisX.title); | |
// Creating the y axis. | |
svg.append("g") | |
.attr("class", axisY.axisClass) | |
.call(yAxis.scale(yScale).tickFormat(yScale.tickFormat(10, ",.1s"))) | |
.append("text") | |
.attr("class", axisY.titleClass) | |
.attr("transform", "rotate(-90)") | |
.attr("x", axisY.x) | |
.attr("y", axisY.y) | |
.attr("dy", axisY.dy) | |
.style("text-anchor", axisY.textAnchor) | |
.text(axisY.title); | |
// Creating clipPath - prevents circles from | |
// being drawn outside the chart | |
svg.append("clipPath") | |
.attr("id", "chart-area") | |
.append("rect") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("width", width) | |
.attr("height", height); | |
// Creating the bubble chart. | |
var g = svg.append("g") | |
.attr("class", "group") | |
.attr("clip-path", "url(#chart-area)"); | |
var circles = g.selectAll("circle") | |
.data(data.sort(function (a, b) { | |
return b.radius - a.radius; | |
})); | |
// Exit | |
circles.exit().remove(); | |
// Enter | |
circles.enter().append("circle") | |
.attr("class", circleClass) | |
.attr("r", function (d) { return d.radius; }); | |
// Update | |
circles | |
.attr("cx", function (d) { return xScale(d.x); }) | |
.attr("cy", function (d) { return yScale(d.y); }) | |
.attr("stroke", stroke) | |
.attr("stroke-width", strokeWidth) | |
.style("fill", function (d) { return color(d.color); }) | |
.style("opacity", opacity) | |
.on("mouseover", function (d, i) { | |
return dispatch.mouseover.call(this, d, i); | |
}) | |
.on("mouseout", function (d, i) { | |
return dispatch.mouseout.call(this, d, i); | |
}); | |
}); | |
} | |
// Public API | |
chart.margin = function (_) { | |
if (!arguments.length) { return margin; } | |
margin.top = typeof _.top !== "undefined" ? _.top : margin.top; | |
margin.right = typeof _.right !== "undefined" ? _.right : margin.right; | |
margin.bottom = typeof _.bottom !== "undefined" ? _.bottom : margin.bottom; | |
margin.left = typeof _.left !== "undefined" ? _.left : margin.left; | |
return chart; | |
}; | |
chart.width = function (_) { | |
if (!arguments.length) return width; | |
width = _; | |
return chart; | |
}; | |
chart.height = function (_) { | |
if (!arguments.length) return height; | |
height = _; | |
return chart; | |
}; | |
chart.color = function (_) { | |
if (!arguments.length) return color; | |
color = _; | |
return chart; | |
}; | |
chart.x = function (_) { | |
if (!arguments.length) return x; | |
x = _; | |
return chart; | |
}; | |
chart.y = function (_) { | |
if (!arguments.length) return y; | |
y = _; | |
return chart; | |
}; | |
chart.xScale = function (_) { | |
if (!arguments.length) return xScale; | |
xScale = _; | |
return chart; | |
}; | |
chart.yScale = function (_) { | |
if (!arguments.length) return yScale; | |
yScale = _; | |
return chart; | |
}; | |
chart.radius = function (_) { | |
if (!arguments.length) return radius; | |
radius = _; | |
return chart; | |
}; | |
chart.stroke = function (_) { | |
if (!arguments.length) return stroke; | |
stroke = _; | |
return chart; | |
}; | |
chart.strokeWidth = function (_) { | |
if (!arguments.length) return strokeWidth; | |
strokeWidth = _; | |
return chart; | |
}; | |
chart.opacity = function (_) { | |
if (!arguments.length) return opacity; | |
opacity = _; | |
return chart; | |
}; | |
chart.fill = function (_) { | |
if (!arguments.length) return fill; | |
fill = _; | |
return chart; | |
}; | |
chart.dispatch = function (_) { | |
if (!arguments.length) return dispatch; | |
dispatch = _; | |
return chart; | |
}; | |
chart.circleClass = function (_) { | |
if (!arguments.length) return circleClass; | |
circleClass = _; | |
return chart; | |
}; | |
chart.axisX = function (_) { | |
if (!arguments.length) { return axisX; } | |
axisX.axisClass = typeof _.axisClass !== "undefined" ? _.axisClass : axisX.axisClass; | |
axisX.titleClass = typeof _.titleClass !== "undefined" ? _.titleClass : axisX.titleClass; | |
axisX.x = typeof _.x !== "undefined" ? _.x : axisX.x; | |
axisX.y = typeof _.y !== "undefined" ? _.y : axisX.y; | |
axisX.dy = typeof _.dy !== "undefined" ? _.dy : axisX.dy; | |
axisX.textAnchor = typeof _.textAnchor !== "undefined" ? _.textAnchor : axisX.textAnchor; | |
axisX.title = typeof _.title !== "undefined" ? _.title : axisX.title; | |
return chart; | |
}; | |
chart.axisY = function (_) { | |
if (!arguments.length) { return axisY; } | |
axisY.axisClass = typeof _.axisClass !== "undefined" ? _.axisClass : axisY.axisClass; | |
axisY.titleClass = typeof _.titleClass !== "undefined" ? _.titleClass : axisY.titleClass; | |
axisY.x = typeof _.x !== "undefined" ? _.x : axisY.x; | |
axisY.y = typeof _.y !== "undefined" ? _.y : axisY.y; | |
axisY.dy = typeof _.dy !== "undefined" ? _.dy : axisY.dy; | |
axisY.textAnchor = typeof _.textAnchor !== "undefined" ? _.textAnchor : axisY.textAnchor; | |
axisY.title = typeof _.title !== "undefined" ? _.title : axisY.title; | |
return chart; | |
}; | |
d3.rebind(chart, dispatch, "on"); | |
return chart; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment