Skip to content

Instantly share code, notes, and snippets.

@jkeohan
Last active November 4, 2015 22:50
Show Gist options
  • Save jkeohan/6603773519296973f589 to your computer and use it in GitHub Desktop.
Save jkeohan/6603773519296973f589 to your computer and use it in GitHub Desktop.
D3 Intermediate - Module 1
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
<script type="text/javascript" src="reuseable.d3.charts.js"></script>
<script src="https://rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script>
<!-- Bootstrap -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Additional CSS -->
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.min.css">
<link rel="stylesheet" href="main.css">
<link href="http://fonts.googleapis.com/css?family=Lato:400,600" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato:400,600" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Lato:400,600" rel="stylesheet" type="text/css">
<link href='http://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="hero-shot"></div>
<div class="main-content">
<div class="containter main">
<h1>D3 ScatterPlot on Renewable Energy</h1>
<p class="intro">
This ScatterPlot is intended to show the percentage of Renewable Energy production of 41 countries from 2002 to 2012. Certain
regions, such as Scandanavia, clearly stand out as the leader in the global adoption of renewable energy technologies.
</p>
<span>The data set was provided by OECD: </span><a href="https://data.oecd.org/energy/renewable-energy.htm#indicator-chart">https://data.oecd.org/energy</a>
<hr class="divider">
</div>
<a name="section1"></a>
<div class="container main">
<h1>Scatter Plot on Regional Growth</h1>
<div class="row">
<div class="col-md-8" id="reduceWidth" style="margin-bottom:40px">
<div class="switch">
<form>
<label>Regions<input type="radio" name="choice" value="Regions" class="radio_buttons" checked></label>
<label>Countries<input type="radio" name="choice" value="Countries" class="radio_buttons"></label>
</form>
</div>
<div class="regionalstats" ></div>
</div>
<div class="col-md-4" id="expandWidth">
<div class="panel panel-success">
<div class="panel-heading"><h3>Functional D3 Components</h3></div>
<div class="panel-body">
<p>Some of the d3.methods used in the importing and formatting data used to render the scatterplot included:</p>
<table>
<tr class="section1">
<td>d3.csv</td>
<td>d3.map</td>
<td>d3.set</td>
<td>d3.keys</td>
</tr>
<tr class="section1">
<td>d3.mean</td>
<td>d3.nest</td>
<td>d3.extent</td>
<td>d3.transition</td>
</tr>
</table>
<br>
<p>Additional functionality included:
<ul>
<li>Radio Buttons that transition regions/countries</li>
<li>Resuable Legend Module</li>
</ul>
<p>This component was created following best practices outlined by Chris Viau in his book: <a href="http://bleedingedgepress.com/our-books/developing-a-d3-js-edge/">Developing a D3.js Edge"</a> and is called using <code>d3.models.legend()</code>.</p>
<pre><code>var rlegend = d3.models.legend()
.fontSize(15)
.width(width-160)
.height(height)
.inputScale(colorScale);
svg.call(rlegend);
</code></pre>
</div>
</div>
</div>
<hr class="divider">
</div>
</div>
</div>
<script type="text/javascript" src="scatterplot.js"></script>
</body>
</html>
/*** Start Navigation ***/
.nav {
/*1. images overflowed below the nav...R=added overflow hidden and revmoved set height
There is
*/
/* height:50px;*/
background-color: #85b433;
border-bottom: 10px solid #FFB266;
opacity:.8;
}
.nav a {
color: #244774;
font-family: 'Poiret One';
font-size: 25px;
font-weight: bold;
padding: 14px 10px;
/*text-transform: uppercase;*/
text-decoration: none;
}
.nav li{
/* 1. display: inline shortens the border to 1/4; */
/* 2. display: block: stacks the li's; */
display:inline-block;
}
.pull-left.border li+li {
border-left: 3px solid #FFB266;
/* height:50px;*/
}
.nav .pull-left img {
max-height:50px;
}
.nav ul {
/*1. ul with images had margin-bottom:10px set by bootstrap css. clearing that option then
changed it to 14px but I couldn't find where that was configured.
Grayed out rules are the unset rules, which use a special default stylesheet that is
applied to all elements(the rules that make the element renderable, because all styles have to have a value).
*/
margin:auto;
}
.nav ul.chart-types{
margin-top:8px;
/*margin-left:20px;*/
}
/*** End Navigation ***/
/*** Start Hero-Shot ***/
.hero-shot {
background-image: url(http://biopact.com/wp-content/uploads/2013/01/cropped-human-hand-holding-a-city.jpg);
width:auto;
height:400px;
background-repeat: no-repeat;
background-size: 100%;
}
/*** End Hero-Shot ***/
/*** Start Main-Content ***/
#fitwidth{
max-width: 970px !important;
}
.main-content{
margin-left:5%;
margin-right:5%;
margin-top:-5%;
background: white;
padding-top:10px;
padding-left:5px;
padding-right: 5px;
}
.main-content .main{
width:100%;
}
.divider{
width:200px;
margin-top:40px;
margin-bottom:20px;
border: 3px solid #85b433;
clear:both;
}
.number {
width: 40px;
background-color: #85b433;;
color: #fff;
height: 40px;
text-align: center;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
margin-top: -10px;
font-weight: 300;
line-height: 1.5em;
font-size: 0.8em;
}
.intro {
font-size: 18px;
}
/*** End Main-Content ***/
/**** Start D3 Specific ****/
.Axis line {
stroke: #000;
stroke-width: .1;
}
.Axis path {
display:none;
}
.Axis text {
font-size: 10px;
}
/**** Start Scatterplot ****/
#reduceWidth{
max-width: 60%;
}
#expandWidth{
width: 40% ;
}
.panel {
width: 420px;
}
.panel-heading{
text-align: center;
}
.panel-heading h3{
color:black;
margin:0px;
}
pre code{
font-size: 13px !important;
}
/**** Start Radio Button ****/
.switch {
position: absolute;
top: 20px;
left: 70px;
}
.switch label:last-of-type{
margin-left:15px;
}
.switch input {
margin-left:5px;
}
.switch label{
font-weight: normal;
font-size:15px;
}
/**** End Radio Button ****/
/**** Start Tooltip ****/
.d3tooltip {
position: absolute;
padding: 5px;
/*pointer-events: none;*/
border: 1px solid green;
border-radius: 12px;
line-height: 20px;
opacity: .07;
background-color:white;
}
.d3tooltiphr {
margin:2px 0;
}
.regionName{
font-size:12px;
font-weight: bold;
text-align: center;
display:block;
margin-bottom:-20px;
}
.value {
font-size:12px;
font-weight: bold;
margin-top:-10px;
}
.key {
font-size:12px;
}
/**** End Tooltip ****/
/**** Start Table ****/
table{
margin:auto;
/*width:50%;*/
}
tr.section1{
border:white;
border-bottom: 1px solid #E7E7E7;
}
tr.section1:last-of-type{
border:white;
}
tr.section1 td{
border-right:1px solid #E7E7E7;;
font-size:15px !important;
}
tr.section1 td:last-of-type{
border-right:white;
}
/**** End Table ****/
/*** End Scatterplot ***/
/*** Start Bar Graph ***/
.allContent {
width:1000px;
}
.barGraph-title h2{
text-align: center;
}
.barGraphText{
position:absolute;
top:0px;
right:200px;
}
.enter, .update{
font-weight: normal;
font-size:13px;
}
.playAll {
margin-left:20px;
margin-bottom:0px;
cursor:pointer;
}
.buttonContainer {
margin:10px auto;
display: inline-block;
text-align: center;
width:100%;
overflow:hidden;
}
.button {
display: inline-block;
margin-left: 10px;
/* font-size: 15px;
*/ border: 1px solid black;
padding:5px;
cursor:pointer;
}
.button.selected {
font-weight: bold;
border: 3px solid green;
color:#296629;
}
.clearfix {
clear:both;
}
#section2 .col-md-4{
padding-top:10px;
}
/*** End Bar Graph ***/
/*** Start Line Graph ***/
path:hover {
fill: #EED6A5;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
.line {
stroke: black;
/* stroke-width: 10px;*/
opacity: 0.7;
fill: none;
}
.line:hover {
/* stroke: green;*/
/* stroke-width:5px;*/
opacity:1;
}
.label{
font-size: small;
font-family: avenir;
}
/**** Start Tooltip ****/
.s3tooltip {
position: absolute;
padding: 5px;
pointer-events: none;
border: 1px solid green;
border-radius: 12px;
line-height: 20px;
opacity: .07;
background-color:white;
}
.tooltipTail {
position: absolute;
/* width: 0;
height: 0; */
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
/* border-right:25px solid green; */
}
.tooltipTail.hidden{
display:none;
opacity:0;
}
.tooltipTail.show{
opacity:1;
}
/**** End Tooltip ****/
/**** Start Table ****/
#modal {
position:absolute;
left: 50px;
top:0px;
z-index:1;
background: white;
border: 1px black solid;
/*5px solid rgba(255, 255, 255, .5);*/
/*box-shadow: 10px 10px 5px #888888;*/
width:210px;
}
table{
width:200px;
margin:auto;
}
tr {
border: 1px gray solid;
width:200px;
opacity:1;
}
td {
font-size: 8px;
padding-right:15px;
padding-left:10px;
text-align: center;
/* min-width: 125px;*/
}
td.data {
font-weight: 900;
}
.sideBar{
height:400px;
position: absolute;
top: 40px;
right: 370px;
}
.fcomponents {
clear:both;
}
/**** End Table ****/
/*** End Line Graph ***/
d3.models = {};
//var rlegend = d3.edge.legend().fontSize(15)
//svg.datum(yearMean).call(rlegend)
d3.models.legend = function () {
var fontSize = 15;
var width = 650;
var height = 400;
var legendValues;
var dispatch = d3.dispatch("mouseOver", "mouseOut");
function render(selection) {
//console.log(selection)
selection.each(function(_data) {
//console.log(_data)
var legend = selection.selectAll("legend").data(legendValues).enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"})
legend.append('rect')
.attr({ x:width+5, y:5, width: 10, height: 10 })
.style("fill", function (d, i) { return d.color;
})
legend.append('text')
.attr({ x: width+25, y: 15})
.text(function (d, i) { return d.text})
.attr("class", "textselected")
.style("text-anchor", "start")
.style("font-size", fontSize)
.on("mouseover",dispatch.mouseOver)
.on("mouseout", dispatch.mouseOut)
})//_selection.each()
}//render()
render.fontSize = function(_x) {
if (!arguments.length) return fontSize;
fontSize = _x;
return this;
}
render.width = function(_x) {
if (!arguments.length) return width;
width = _x;
return this;
}
render.height = function(_x) {
if (!arguments.length) return height;
height = _x;
return this;
}
render.inputScale = function(_x) {
if (!arguments.length) return inputScale;
scale = _x;
legendValues = [];
scale.domain().forEach(function (el) {
var cellObject = {color: scale(el), text: el}
legendValues.push(cellObject)
//console.log(legendValues)
})
return this;
}
d3.rebind(render, dispatch, "on")
return render
}
( function () {
var m = {top:50,bottom:60,left:70,right:150};
var width = 650 - m.left - m.right;
var height = 500 - m.top - m.bottom;
var currentYear = "2002";
var tooltip;
var grouped = true;
var svg = d3.select(".regionalstats").append('svg')
.attr("width",width + m.left + m.right)
.attr("height", height + m.top + m.bottom)
.append('g').translate([m.left,m.top]);//testing jetpack
//.append('g').attr("transform","translate(" + m.left + "," + m.top + ")")//.attr("transform","translate(50,50)")
//Create scales
var yScale = d3.scale.linear().range([height,0]);
var xScale = d3.scale.linear().range([0,width]);
var radiusScale = d3.scale.sqrt().range([6,20])
//var radiusScale = d3.scale.linear().range([6,20])
var colorScale = d3.scale.category10();
//Create axes
var yAxis = d3.svg.axis().scale(yScale).orient("left")
.innerTickSize(-width)
.tickFormat(function(d) { return d + "%" } );
var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
.innerTickSize(-height)
.tickFormat(function(d) { return d + "%" } );
svg.append("g").attr("class","y Axis")
.append("text")
.attr({ class: "ylabel", y: -60, x: -290, dy: ".71em" })
.attr("transform", "rotate(-90)")
.text("2012 Renewable Energy Output").style("font-size",20);
svg.append('g').attr("class","x Axis").attr("transform","translate(0," + height + ")")
.append("text").style("text-anchor", "middle")
.attr({ class: "xlabel", x: width/2 , y: 50})
.text("2002 Renewable Energy Output").style("font-size",20);
//API call for csv data and all formatting of data
d3.csv("world_data.csv", function(data) {
//d3.nest to rollup Region and mean of years
var regions = d3.set(data.map(ƒ('Region')))//testing jetpack
.values().filter(function(d) { return !(d == "World")}).sort(d3.acscending);
colorScale.domain(regions);
//Create the legend
var rlegend = d3.models.legend().fontSize(15).width(width).height(height).inputScale(colorScale);
svg.call(rlegend);
var yearMean = d3.nest().key(function(d) { return d["Region"] } ).sortKeys(d3.ascending)
.rollup(function(v) {
//console.log(v)// [Object, Object] each obj is a row of data
return { mean: mean(v), countries: v.map(function(c) { return c.Location} ) }
} )
.entries(data);
function mean(val) {
var obj = {};
var keys = d3.keys(data[0]).filter(function(key) { return !(key == "Location" || key == "Region") })
keys.forEach(function(year) {
var y = d3.mean(val, function(m) { return +m[year]
} )
obj[year] = d3.format(".2f")(y)
})
return obj
};
colorize(yearMean)
function colorize (yearMean) {
yearMean.forEach( function(d,i) {
d.color = colorScale(d.key);
})
}
var yearMeanNoWorld = yearMean.filter(function(d) { return !(d.key == "World") })
//Converted yearMean object to format consistent with csv import.
var formatYear = (function () {
var array = []
yearMean.forEach(function(d) {
var obj = {};
obj["Region"] = d.key
obj["countries"] = d.values.countries
//d3.entries will create new array with key\value property names
d3.entries(d.values.mean).forEach(function(item) {
obj[item.key] = item.value
})
obj["color"] = d.color
array.push(obj)
})
return array
}
)()
//Add radio buttons
var radio_buttons = d3.selectAll('.radio_buttons')
.on("click", function() {
var value = this.value
if(value == "Regions") { regionChart(data,yearMean,currentYear,formatYear) }
else { countryChart(data,currentYear,yearMean,formatYear) }
} )
//Call the chart
regionChart(data,yearMean,currentYear,formatYear)
})//end csv
function countryChart(data,year,yearMean,formatYear) {
grouped = false;
var yearMean = formatYear
var filterOutWorld = data.filter(function(d,i) { return !(d["Location"] == "World")} )
var locations = (data.filter(function(d) { return !(d.Location == "World") } ) ).map(function(d) { return d.Location } )
var regions = d3.set(data.map(function(d) { return d.Region } ) ).values().sort(d3.acscending);
var circles = svg.selectAll("circle").data(filterOutWorld)
circles.enter().append("circle")
.attr("cy", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj["2012"] }})
return yScale(val)
})
.attr("cx", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj[year] }})
return xScale(val)
})
.attr("r", function(d) { d.radius = 5; return 5 })
.attr("class",function(d) { return d.Location + " " + "Country" })
.style("fill",function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = obj.color
d.color = val
}})
return val
})
.style("opacity",.8)
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.append('title');
circles.attr("cy", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj["2012"]
}})
return yScale(val)
})
.attr("cx", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj[year] }})
return xScale(val)
})
.attr("r", function(d) { d.radius = 5; return 5 })
.attr("class",function(d) { return d.Location + " " + "Country" })
.style("fill",function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = obj.color
d.color = val }})
return val
})
.style("opacity",.8)
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.append('title');
yScale.domain([0,d3.max(data, function(d) { return +d["2012"] + 7 } ) ] )//.range([height,0])
xScale.domain([0,d3.max(data, function(d) { return +d[year] + 4 } ) ] )//.range([0,width])
circles.transition().duration(2000)
.attr("cy", function(d,i) { return yScale(+d["2012"]) })
.attr("cx", function(d,i) { return xScale(+d[year]) })
.attr("r",5)
d3.selectAll(".Region").transition().duration(2000).attr("r",0).remove()
//Update Axises
svg.select(".x.Axis").transition().duration(2000).call(xAxis);
svg.select(".y.Axis").transition().duration(2000).call(yAxis);
}
function regionChart(data,yearMean,year,formatYear) {
grouped = true
var yearMean = formatYear.filter(function(d) { return !(d.Region == "World") })
var filterOutWorld = data.filter(function(d,i) { return !(d["Location"] == "World")} )
var locations = (data.filter(function(d) { return !(d.Location == "World") } ) ).map(function(d) { return d.Location } )
var regions = d3.set(data.map(function(d) { return d.Region } ) ).values().sort(d3.acscending)
yScale.domain([0,d3.max(yearMean, function(d) { return +d["2012"] + 7 } ) ] )//.range([height,0])
xScale.domain([0,d3.max(yearMean, function(d) { return +d[year] + 4 } ) ] )//.range([0,width])
radiusScale.domain(d3.extent(yearMean, function(d) { return +d.countries.length } ) )
var circles = svg.selectAll("circle").data(yearMean)
circles.enter().append("circle")
.attr("class",function(d) { return d.Region})
.attr("r",20)
circles
.attr("radius",5)
.attr("class",function(d) { return d.Region + " " + "Region"})
.style("fill",function(d,i) { return d.color })
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.append('title')
circles.transition().duration(3000).style("opacity",.8)
.attr("r", function(d) { d.radius = radiusScale(+d.countries.length)
return radiusScale(+d.countries.length)})
.attr("cy", function(d,i) { return yScale(+d["2012"]) })
.attr("cx", function(d,i) { return xScale(+d[year]) })
d3.selectAll(".Country").transition().duration(3000)
.attr("cy", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj["2012"]
}})
return yScale(val)
})
.attr("cx", function(d) {
var val;
yearMean.forEach(function(obj) { if(d.Region == obj.Region) {
val = +obj[year]
}})
return xScale(val)
}).style("opacity",0).remove()
svg.select(".x.Axis").transition().duration(2000).call(xAxis);
svg.select(".y.Axis").transition().duration(2000).call(yAxis);
}
function mouseOver(d) {
var c = d3.select(this)
var cx = +c.attr("cx")
var cy = +c.attr("cy")
c.call(displayToolTip,d,cx,cy)
var radiusOver = c.node().r.animVal.value;
c.transition().duration(250)
.attr("stroke-width",20)
.attr("stroke", "rgba(230,230,230, .8)")
.attr("r", d.radius + 10)
var line1 = svg.append("line").datum(d)
line1.call(createLine1)
var line2 = svg.append("line").datum(d)
line2.call(createLine2)
}
function mouseOut(d) {
var c = d3.select(this)
c.transition().duration(250)
.attr("stroke-width",0)
.attr("stroke", "rgba(230,230,230, .8)")
.attr("r",d.radius )
d3.selectAll(".line1").transition().duration(250).style("opacity",0).remove()
d3.selectAll(".line2").transition().duration(250).style("opacity",0).remove()
tooltip.transition().duration(250).style('opacity',0).remove()
}
function createLine1() {
this
.attr("x1",xScale(0) )
.attr("y1", yScale(+this.datum()["2012"] ) )
.attr("x2", xScale(+this.datum()[currentYear]) )
.attr("y2", yScale(+this.datum()["2012"]) )
.attr("stroke-width", 1)
.attr("stroke", this.datum()["color"] ) //d3.select(this).style("fill") )
.style("opacity",1)
.attr("class","line1")
}
function createLine2(){
this
.attr("x1", xScale(+this.datum()[currentYear]) )
.attr("y1", height )
.attr("x2", xScale(+this.datum()[currentYear]) )
.attr("y2", yScale(+this.datum()["2012"]))
.attr("stroke-width", 1)
.attr("stroke", this.datum()["color"] )
.style("opacity",1)
.attr("class","line2")
//.attr("r",radiusOver + 10)
}
function displayToolTip(selection,d,cx,cy) {
tooltip = d3.select(".regionalstats").append("div").attr("class","d3tooltip")
tooltip.style("font-size", 10)
tooltip.style("border" , "3px solid " + d.color )
.transition().duration(250).style("opacity",1)
if(grouped) {
tooltip.html(
'<span class="regionName">' + d.Region + '</span><br/>' +
'<hr class="d3tooltiphr" style="border: 1px solid ' + d.color + ' " ' + '>' +
'<span class="key">2002:</span> <span class="value">' + +d["2002"] + '%</span><br/>' +
'<span class="key">2012:</span> <span class="value">' + +d["2012"] + '%</span><br/>' +
'<hr class="d3tooltiphr" style="border: 1px solid ' + d.color + ' " ' + '>' +
'<span class="key">Countries:</span> <span class="value">' + d.countries.length + '</span>')
.style("left", function() {
if ((cx + 100) > width ) { return (cx -30) + "px" }
else { return (cx + 100) + "px" }
} )
.style("top", (cy) + "px")
}
else {
tooltip.html(
'<span class="regionName">' + d.Location + '</span><br/>' +
'<hr class="d3tooltiphr" style="border: 1px solid ' + d.color + ' " ' + '>' +
'<span class="key">2002:</span> <span class="value">' + +d["2002"] + '%</span><br/>' +
'<span class="key">2012:</span> <span class="value">' + +d["2012"] + '%</span><br/>')
//'<hr class="d3tooltiphr" style="border: 1px solid ' + color + ' " ' + '>')
.style("left", function() {
if ((cx + 100) > width ) { return (cx -30) + "px" }
else { return (cx + 100) + "px" }
} )
.style("top", (cy) + "px")
}
return tooltip
}
})()
Location 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 Region
Australia 6.2 6 5.8 5.7 5.8 5.8 5.8 4.6 4.8 5.1 4.6 Oceana
Austria 21.3 18.7 19.7 21 22.1 24.1 25.3 27.8 27.2 26.6 29.5 Europe
Belgium 1.3 1.5 1.6 2 2.3 2.7 3.1 3.8 4.2 4.9 5.1 Europe
Brazil 39.4 42 42.3 42.9 43.3 44.4 44.5 45.8 44 42.7 42.2 Latin America
Canada 16.9 15.6 15.6 15.9 15.7 16.2 16.8 17.5 17.1 18 17.9 North America
Chile 26.2 24.8 24.2 25.1 25.3 23.5 24.4 26.1 22 23.1 24.1 Latin America
China 18.4 16.2 14.5 13.7 12.8 12.5 12.6 12.1 11.4 10.7 9.8 Asia
Czech Republic 3.7 3.4 3.8 4 4.2 4.7 4.9 5.8 6.3 6.9 7.5 Europe
Denmark 11 11.9 13.6 15 14.2 16.1 16.7 17.8 20 22.2 24.4 Scandanavia
Estonia 11.7 11.2 11.4 11.4 10.5 10.7 11.9 15.2 15.3 14.8 14.5 Europe
Finland 22.4 21.3 23.4 23.6 23.3 23.5 25.8 24 25.4 26.1 29.1 Scandanavia
France 5.8 5.8 5.8 5.7 5.9 6.3 7.1 7.5 7.9 7.2 7.9 Europe
Germany 3.2 3.8 4.4 5 5.8 7.9 8 8.8 9.9 10 10.7 Europe
Greece 4.9 5.3 5.3 5.4 5.9 5.7 5.6 6.4 7.7 7.9 8.7 Europe
Hungary 3.4 3.5 3.6 4.3 4.5 5.1 6 7.4 7.6 7.6 8 Europe
Iceland 75 75.2 74.8 75.9 78.4 81.6 81.3 81.8 82.5 83.8 84.7 Scandanavia
India 33.2 32.9 31.7 31.2 30.4 29.9 28.9 26.8 26.5 26.5 26.4 Asia
Indonesia 37.3 37.4 35.5 34.9 34.7 35.3 36.2 34.8 33.9 33.6 33.4 Asia
Ireland 1.8 1.7 2 2.5 2.9 3.2 3.9 4.6 4.7 6.2 6.1 Europe
Israel 3.6 3.5 3.8 4 3.7 3.7 4.7 5 5 4.9 4.8 Middle East
Italy 5.8 6 6.6 6.3 6.9 6.7 7.7 9.7 10.6 11.9 13.2 Europe
Japan 3.2 3.4 3.3 3.2 3.4 3.2 3.3 3.4 3.9 4.2 4.2 Asia
Korea 0.4 0.5 0.5 0.5 0.6 0.6 0.6 0.7 0.7 0.7 0.7 Asia
Luxembourg 1.1 1 1.2 1.6 1.8 3.1 3.1 3.3 3.1 2.9 3.2 Europe
Mexico 10.2 10.2 10.4 10.3 9.9 9.9 10 9.5 9.8 9.3 8.7 Latin America
Netherlands 1.9 1.8 2.1 2.7 3 3 3.5 4 3.8 4.3 4.3 Europe
New Zealand 29.8 29.7 31.3 31.6 32 32.2 32.9 35.8 38.9 40.4 38.3 Oceana
Norway 49.5 38.2 40 48.5 42.6 46.5 44.9 40.9 36.1 42.8 46.9 Scandanavia
Poland 4.7 4.6 4.7 4.8 4.8 5 5.7 6.7 7.2 7.8 8.8 Europe
Portugal 13.7 16.9 14.7 13.1 17.1 17.7 17.7 19.9 23.3 22.3 21.2 Europe
Russia 2.8 2.7 2.9 2.9 2.8 2.9 2.6 2.8 2.5 2.4 2.3 Asia
Slovak Republic 4 3.5 4 4.3 4.5 5.3 5.1 6.8 7.4 7.4 7.6 Europe
Slovenia 10.5 10.3 11.5 10.6 10.5 10.1 11 14.2 14.7 13.1 13.9 Europe
South Africa 12.1 11.3 10.5 10.7 11 10.2 9.7 10.1 10.3 10.5 10.6 Africa
Spain 5.4 6.9 6.3 5.9 6.5 7 7.6 9.7 11.7 11.7 11.9 Europe
Sweden 25.3 24.5 25 28.8 28.7 30.5 31.5 34.8 33.9 32.1 35.6 Scandanavia
Switzerland 16.8 16.8 16.4 16 15.5 17.8 17.8 17.8 19 18.1 20.5 Europe
Turkey 13.5 12.9 13.3 12 11.1 9.6 9.5 10.2 11.1 10 10.2 Asia
United Kingdom 1.2 1.2 1.5 1.8 1.9 2.2 2.6 3.2 3.3 4.1 4.5 Europe
United States 4 4.3 4.4 4.5 4.8 4.7 5.1 5.4 5.6 6.1 6.3 North America
European Union 5.7 5.9 6.3 6.5 6.9 7.6 8.2 9.2 10 10.2 10.5 Europe
World 12.7 12.6 12.4 12.4 12.4 12.5 12.7 13.1 13 13 13 World
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment