graph for daily IFR traffic. data from Eurocontrol/PRU (hence Network Manager): http://www.eurocontrol.int/prudata/dashboard/eur_view_2014.html
Created
August 18, 2015 21:07
-
-
Save espinielli/a365ae239aff6930ead0 to your computer and use it in GitHub Desktop.
Number of IFR flights in EU with D3
This file contains 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
entity | year | days | ifr_flights | avg_daily | per_cent_change | |
---|---|---|---|---|---|---|
SES AREA RP1 | 2008 | 274 | 7502370 | 27381 | 0 | |
SES AREA RP1 | 2009 | 273 | 6894634 | 25255 | -7.8 | |
SES AREA RP1 | 2010 | 273 | 6885295 | 25221 | -0.1 | |
SES AREA RP1 | 2011 | 273 | 7129303 | 26115 | 3.5 | |
SES AREA RP1 | 2012 | 274 | 6963553 | 25414 | -2.7 | |
SES AREA RP1 | 2013 | 273 | 6824176 | 24997 | -1.6 | |
SES AREA RP1 | 2014 | 273 | 6960433 | 25496 | 2.0 |
This file contains 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> | |
<meta charset="utf-8"> | |
<style> | |
.bar { | |
fill: steelblue; | |
} | |
.bar:hover { | |
fill: brown; | |
} | |
.axis { | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.x.axis path { | |
/*display: none;*/ | |
} | |
.hidden{ | |
display: none; | |
} | |
#loading { | |
text-align: center; | |
position: absolute; | |
padding-left: 200px; | |
padding-top: 100px; | |
height: 20px; | |
font: 16px sans-serif; | |
} | |
#tooltip { | |
position: absolute; | |
width: auto; | |
height: auto; | |
padding: 2px 2px; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
-webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4); | |
-moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4); | |
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4); | |
pointer-events: none; | |
background-color: #bbb; | |
} | |
#tooltip p { | |
margin: 0 0 0 0; | |
padding: 2px 2px; | |
font-family: sans-serif; | |
font-size: 14px; | |
} | |
.axis .minor line { | |
stroke: #777; | |
stroke-dasharray: 2,2; | |
} | |
.line { | |
fill: none; | |
stroke: red; | |
stroke-width: 1.5px; | |
} | |
</style> | |
<body> | |
<div id="tooltip" class="hidden"> | |
<p id="tip"></p> | |
</div> | |
<div id="chart"> | |
<div id="loading">Loading...</div> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
// define size and margings | |
var margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
width = 700 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
// x, y and z axes: type (ordinal/linear/...), ranges, ticks formatting | |
var x = d3.scale.ordinal() | |
.rangeRoundBands([0, width], 0.15); | |
var y = d3.scale.linear() | |
.range([height, 0]); | |
var z = d3.scale.linear() | |
.range([height, 0]); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickFormat(d3.time.format("%Y")); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left"); | |
var zAxis = d3.svg.axis() | |
.scale(z) | |
.orient("right"); | |
// chart creation and positioning | |
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 + ")"); | |
// pointers to <div>s | |
var loading = d3.select("#loading"); | |
var tooltip = d3.select("#tooltip").classed("hidden", true); | |
var tip = d3.select("#tip") | |
// register on mouseover event for tooltip management | |
svg.on("mousemove", function() { | |
// update tooltip position | |
tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px"); | |
return true; | |
}); | |
// the line | |
var line = d3.svg.line() | |
.x(function(d) { return x(d.year) + x.rangeBand()/2; }) | |
.y(function(d) { return z(d.per_cent_change); }); | |
// the zero line | |
// TODO | |
// read the data and draw the chart | |
d3.csv("data.csv", function(error, data) { | |
if (error) return console.error(error); | |
loading.classed("hidden", true); | |
// properly read the data | |
var parseDate = d3.time.format("%Y").parse; | |
data.forEach(function(d) { | |
d.year = parseDate(d.year); | |
d.avg_daily = + d.avg_daily; | |
d.per_cent_change = +d.per_cent_change; | |
}); | |
x.domain(data.map(function(d){return d.year;})); | |
y.domain(d3.extent(data, function(d) { return d.avg_daily; })).nice(); | |
z.domain(d3.extent(data, function(d) { return d.per_cent_change; })).nice(); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis) | |
.append("text") | |
.attr("x", width) | |
.attr("dy", "3em") | |
.style("text-anchor", "end") | |
.text("Year"); | |
svg.append("g") | |
.attr("class", "y axis left") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".65em") | |
.style("text-anchor", "end") | |
.text("Avg. daily EU IFR flights"); | |
// bar chart | |
svg.selectAll(".bar") | |
.data(data) | |
.enter().append("rect") | |
.attr("class", "bar") | |
.attr("x", function(d) { return x(d.year); }) | |
.attr("width", x.rangeBand()) | |
.attr("y", function(d) { return y(d.avg_daily); }) | |
.attr("height", function(d) { return height - y(d.avg_daily); }) | |
.on("mouseover", function(d,i) { | |
d3.select(this).style({'stroke-opacity':1,'stroke':'#F00'}); | |
tooltip.classed("hidden", false); | |
tip.text("" + d.avg_daily + " IFR flights"); | |
}) | |
.on("mouseout", function(d) { | |
this.style.stroke = "none"; | |
tooltip.classed("hidden", true); | |
}); | |
// line chart | |
var gz = svg.append("g") | |
.attr("class", "y axis right") | |
.attr("transform", "translate(" + width + ", 0)") | |
.call(zAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", "-1.0em") | |
.style("text-anchor", "end") | |
.text("year on year (%)"); | |
// gz.selectAll("g.y.axis.right g.tick line") | |
// .attr("x2", function(d) { return d.per_cent_change == 0; }) | |
// .classed("minor", true); | |
svg.append("path") | |
.datum(data) | |
.attr("class", "line") | |
.attr("d", line); | |
// Add the points! | |
svg.selectAll(".point") | |
.data(data) | |
.enter().append("circle") | |
.attr("class", "point") | |
.attr("r", 4.5) | |
.attr("cx", function(d) { return x(d.year) + x.rangeBand()/2; }) | |
.attr("cy", function(d) { return z(d.per_cent_change); }) | |
.on("mouseover", function(d,i) { | |
d3.select(this).style({'stroke-opacity':1,'stroke':'#F00'}); | |
tooltip.classed("hidden", false); | |
tip.text("" + d.per_cent_change + "%"); | |
}) | |
.on("mouseout", function(d) { | |
this.style.stroke = "none"; | |
tooltip.classed("hidden", true); | |
}); | |
// TODO: 0 line | |
// primitive legend: TODO make it better | |
var legend = svg.append("g") | |
.attr("transform", "translate("+(width/2)+")"); | |
legend.append("text") | |
.attr("dy", ".35em") | |
.attr("x", 26) | |
.text("Average daily IFR Flights (EU-wide)"); | |
legend.append("text") | |
.attr("dy", ".35em") | |
.attr("y", 15) | |
.attr("x", 26) | |
.text("(hover with the mouse to see values)"); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment