Last active
February 23, 2017 16:37
-
-
Save Zhenmao/4fb233223561050e948ba7ca2e2451d4 to your computer and use it in GitHub Desktop.
Best Months for Air Travel
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
Month | Departure Delay | Arrival Delay | Cancellation | |
---|---|---|---|---|
1 | 0.211456587951 | 0.245651366454 | 0.0285721360594 | |
2 | 0.23651701579 | 0.274467883268 | 0.0361818296805 | |
3 | 0.225470304663 | 0.255433459397 | 0.0262672661462 | |
4 | 0.172331582309 | 0.204252950047 | 0.0173124057473 | |
5 | 0.165937921104 | 0.198131926313 | 0.010273910469 | |
6 | 0.233087166175 | 0.269869304133 | 0.0179589757913 | |
7 | 0.204089302806 | 0.223034059475 | 0.0168776505699 | |
8 | 0.180267492434 | 0.196774672984 | 0.0160629386277 | |
9 | 0.113254009924 | 0.13153623167 | 0.018326591583 | |
10 | 0.113558849705 | 0.132176086155 | 0.00584137143679 | |
11 | 0.132451191732 | 0.156557201608 | 0.00851946979773 | |
12 | 0.272127393304 | 0.309467885599 | 0.0326245325328 |
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> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title></title> | |
<style type="text/css"> | |
body { | |
font: 12px sans-serif; | |
} | |
h2 { | |
text-align: center; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.label { | |
fill: black; | |
} | |
.tooltip { | |
position: absolute; | |
text-align: center; | |
min-width: 100px; | |
height: auto; | |
padding: 8px; | |
margin-top: -20px; | |
font: 11px sans-serif; | |
background: none repeat scroll 0 0 #fff; | |
border: 1px solid #eee; | |
opacity: 0.7; | |
pointer-events: none; | |
text-shadow: 1px 1px 0px #fff; | |
} | |
.bubble, | |
.bar { | |
opacity: 0.7; | |
} | |
.bubble-label, | |
.bar-label { | |
fill: #fff; | |
} | |
</style> | |
</head> | |
<body> | |
<h2>Best Months for Air Travel</h2> | |
<div> | |
<p>Air travel delays and cancellations can range from being inconvenient to being a catastrophe that ruins the travel plan. </br>The bubble chart shows the percentages of departure delays (x axis), arrival delays (y axis) and cancellation (bubble area) of each month for US air travels.<sup><a href="#fn1" id="ref1">1</a></sup> </br>The bar charts show the ranking of months according to the percentages.</p> | |
</div> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script type="text/javascript"> | |
// Set margin, width and height | |
var margin = {top: 30, right: 30, bottom: 30, left: 30}, | |
height = 600 - margin.top - margin.bottom, | |
width = 450 - margin.left - margin.right; | |
// Set non-highlight and highlight colors | |
var colorNoHighlight = d3.rgb(128, 177, 211), | |
colorHighlight = d3.rgb(251, 128, 114); | |
// Append a svg for bubble chart | |
var chart1 = d3.select("body") | |
.append("div") | |
.attr("class", "chart") | |
.style("display", "inline-block") | |
.append("svg") | |
.attr("id", "chart1") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("class", "bubble-chart") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// Append a svg for bar charts | |
var chart2 = d3.select("body") | |
.append("div") | |
.attr("class", "chart") | |
.style("display", "inline-block") | |
.append("svg") | |
.attr("id", "chart2") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("class", "bar-charts") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// Get the data | |
d3.csv("2008_rates_by_month.csv", function(data) { | |
data.forEach(function(d) { | |
d["Departure Delay"] = +d["Departure Delay"]; | |
d["Arrival Delay"] = +d["Arrival Delay"]; | |
d["Cancellation"] = +d["Cancellation"]; | |
}); | |
//console.log("data", data); | |
bubbleChart(data); | |
barCharts(data); | |
}); | |
function bubbleChart(data) { | |
/* | |
Bubble Chart | |
x-axis: Percentage of Departure Delays | |
y-axis: Percentage of Arrival Delays | |
bubble area: Percentage of Cancellation | |
*/ | |
// Define the scales | |
var xScale = d3.scaleLinear() | |
.range([0, width]); | |
var yScale = d3.scaleLinear() | |
.range([height, 0]); | |
var rScale = d3.scaleSqrt() | |
.range([0, 60]) | |
// Define the axes | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.ticks(5, "%"); | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(5, "%"); | |
// Set the domains | |
xScale.domain(d3.extent(data, function(d) { return d["Departure Delay"]; })).nice(); | |
yScale.domain(d3.extent(data, function(d) { return d["Arrival Delay"]; })).nice(); | |
rScale.domain([0, d3.max(data, function(d) { return Math.sqrt(d["Cancellation"]); })]).nice(); | |
// Add axes | |
chart1.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis) | |
.append("text") | |
.attr("class", "label") | |
.attr("x", width) | |
.attr("y", -6) | |
.style("text-anchor", "end") | |
.append("tspan") | |
.text("Percentage of ") | |
.append("tspan") | |
.style("font-weight", "bold") | |
.text("Departure Delays"); | |
chart1.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("class", "label") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.append("tspan") | |
.text("Percentage of ") | |
.append("tspan") | |
.style("font-weight", "bold") | |
.text("Arrival Delays"); | |
var bubbles = chart1.selectAll(".bubble") | |
.data(data) | |
.enter(); | |
bubbles.append("circle") | |
.attr("class", function(d) { return "bubble month-" + d["Month"]; }) | |
.attr("r", function(d) { return rScale(d["Cancellation"]); }) | |
.attr("cx", function(d) { return xScale(d["Departure Delay"]); }) | |
.attr("cy", function(d) { return yScale(d["Arrival Delay"]); }) | |
.attr("fill", colorNoHighlight) | |
.on("mouseover", mouseover) | |
.on("mousemove", mousemove) | |
.on("mouseout", mouseout); | |
bubbles.append("text") | |
.attr("class", "bubble-label") | |
.attr("x", function(d){ return xScale(d["Departure Delay"]); }) | |
.attr("y", function(d){ return yScale(d["Arrival Delay"]) + 5; }) | |
.attr("text-anchor", "middle") | |
.text(function(d) { return d["Month"]; }); | |
} | |
function barCharts(data) { | |
/* | |
Bar Chart 1 | |
x-axis: Percentage of Departure Delay | |
y-axis: Month | |
Bar Chart 2 | |
x-axis: Percentage of Arrival Delay | |
y-axis: Month | |
Bar Chart 3 | |
x-axis: Percentage of Cancellation | |
y-axis: Month | |
*/ | |
// Create a bar plot for each data column | |
n = 3; | |
for (var i = 0; i < n; i ++) { | |
barChart(data, i); | |
} | |
} | |
// Sort the data so each bar chart is sorted in increasing order | |
function sortMonths(data, varName) { | |
dataSorted = data.sort(function(a, b) { return a[varName] - b[varName]; }); | |
return dataSorted; | |
} | |
function barChart(data, idx) { | |
// Get the data column name | |
var varName = data.columns[idx + 1]; | |
// Sort the data by the column varName | |
var dataSorted = sortMonths(data, varName) | |
// Define the scales | |
var xScale = d3.scaleBand() | |
.range([0, width]) | |
.paddingInner(0.1) | |
.paddingOuter(0.6); | |
var yAxisHeight = height / n - 20; | |
var yScale = d3.scaleLinear() | |
.range([yAxisHeight, 0]) | |
// Define the axes | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.ticks(12); | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(5, "%"); | |
// Set the domains | |
xScale.domain(dataSorted.map(function(d) { return d["Month"]; })); | |
yScale.domain([0, d3.max(dataSorted, function(d) { return d[varName]; })]); | |
// Append a g for bar chart | |
var barChart = chart2.append("g") | |
.attr("class", "bar-chart") | |
.attr("transform", "translate(0," + (idx * height / n + 20) + ")"); | |
// Add the axes | |
barChart.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("class", "label") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.append("tspan") | |
.text("Percentage of ") | |
.append("tspan") | |
.style("font-weight", "bold") | |
.text(varName); | |
var bars = barChart.selectAll(".bar") | |
.data(dataSorted) | |
.enter(); | |
bars.append("rect") | |
.attr("class", function(d) { return "bar month-" + d["Month"]; }) | |
.attr("x", function(d) { return xScale(d["Month"]); }) | |
.attr("width", xScale.bandwidth()) | |
.attr("y", function(d) { return yScale(d[varName]); }) | |
.attr("height", function(d) { return (yAxisHeight - yScale(d[varName])); }) | |
.attr("fill", colorNoHighlight) | |
.on("mouseover", mouseover) | |
.on("mousemove", mousemove) | |
.on("mouseout", mouseout); | |
bars.append("text") | |
.attr("class", "bar-label") | |
.attr("x", function(d) { return xScale(d["Month"]) + xScale.bandwidth() / 2; }) | |
.attr("y", function(d) { return yScale(d[varName]); }) | |
.attr("dy", "1em") | |
.attr("text-anchor", "middle") | |
.text(function(d) { return d["Month"]; }); | |
} | |
// Add tooltip | |
var div = d3.select("body") | |
.append("div") | |
.attr("class", "tooltip") | |
.style("display", "none"); | |
// Tooltip number formats | |
var formatTooltipPercent = d3.format(".1%"); | |
function mouseover() { | |
div.style("display", "inline-block"); | |
var month = d3.select(this).datum()["Month"]; | |
d3.selectAll(".month-" + month) | |
.style("fill", colorHighlight); | |
} | |
function mousemove(d) { | |
div.style("left", (d3.event.pageX) + 20 + "px") | |
.style("top", (d3.event.pageY - 10) + "px") | |
.html("Month: <b>" + d["Month"] + "</b><br />" + | |
"Percentage of<br />" + | |
"Departure Delay: <b>" + formatTooltipPercent(d["Departure Delay"]) + "</b><br />" + | |
"Arrival Delay: <b>" + formatTooltipPercent(d["Arrival Delay"]) + "</b><br />" + | |
"Cancellation: <b>" + formatTooltipPercent(d["Cancellation"]) + "</b>"); | |
} | |
function mouseout() { | |
div.style("display", "none"); | |
var month = d3.select(this).datum()["Month"]; | |
d3.selectAll(".month-" + month) | |
.style("fill", colorNoHighlight); | |
} | |
</script> | |
</div> | |
</body> | |
<footer> | |
<sup id="fn1">1. The data originally comes from <a href="https://www.transtats.bts.gov/OT_Delay/OT_DelayCause1.asp">RITA</a> for the year <a href="http://stat-computing.org/dataexpo/2009/the-data.html">2008</a>.<a href="#ref1" title="Jump back to footnote 1 in the text.">↩</a></sup> | |
</footer> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment