Skip to content

Instantly share code, notes, and snippets.

@stormpython
Last active November 13, 2015 18:49
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 stormpython/bebb2a4e85a7bf21cde7 to your computer and use it in GitHub Desktop.
Save stormpython/bebb2a4e85a7bf21cde7 to your computer and use it in GitHub Desktop.
European Life Expectancy
[
{ "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 }
]
<!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>
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