Skip to content

Instantly share code, notes, and snippets.

@Zhenmao
Last active February 23, 2017 16:37
Show Gist options
  • Save Zhenmao/4fb233223561050e948ba7ca2e2451d4 to your computer and use it in GitHub Desktop.
Save Zhenmao/4fb233223561050e948ba7ca2e2451d4 to your computer and use it in GitHub Desktop.
Best Months for Air Travel
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
<!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