Origin of data: Open Data Philly
Last active
December 13, 2016 20:35
-
-
Save ctufts/a7acd0ba3d8dfd72bd2773a855184784 to your computer and use it in GitHub Desktop.
Philadelphia Air Quality Index Days - Multi-Series Path, Point, and Tooltip
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
license: gpl-3.0 | |
height: 500 |
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
Year | Good | Moderate | Unhealthy | |
---|---|---|---|---|
1990 | 71 | 214 | 80 | |
1991 | 110 | 179 | 76 | |
1992 | 106 | 197 | 63 | |
1993 | 94 | 175 | 96 | |
1994 | 72 | 184 | 109 | |
1995 | 114 | 171 | 80 | |
1996 | 111 | 147 | 107 | |
1997 | 132 | 159 | 74 | |
1998 | 150 | 178 | 37 | |
1999 | 132 | 203 | 30 | |
2000 | 142 | 198 | 26 | |
2001 | 103 | 223 | 39 | |
2002 | 127 | 188 | 50 | |
2003 | 146 | 188 | 31 | |
2004 | 138 | 204 | 24 | |
2005 | 150 | 187 | 28 | |
2006 | 154 | 178 | 33 | |
2007 | 140 | 193 | 32 | |
2008 | 128 | 217 | 21 | |
2009 | 185 | 175 | 5 | |
2010 | 175 | 165 | 25 | |
2011 | 159 | 192 | 14 | |
2012 | 147 | 198 | 21 | |
2013 | 174 | 185 | 6 | |
2014 | 131 | 228 | 6 |
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 lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Philadelphia Air Quality</title> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<link rel="stylesheet" type="text/css" href="main.css"> | |
</head> | |
<body> | |
<script> | |
// Define margins as per convention: | |
//http://bl.ocks.org/mbostock/3019563 | |
var margin = { | |
top: 20, | |
right: 60, | |
bottom: 20, | |
left: 30 | |
}; | |
var width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var svg = d3.select("body").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 + ")"); | |
// chart title | |
svg.append("text") | |
.attr("x", width / 2) | |
.attr("y", 0) | |
.attr("text-anchor", "middle") | |
.attr("font-family", "sans-serif") | |
.attr("font-size", "16px") | |
.attr("font-weight", "bold") | |
.attr("fill", "black") | |
.text("Air Quality Index Days"); | |
// set up date parsing and scale ranges | |
var parseTime = d3.timeParse("%Y"); | |
var x = d3.scaleTime().range([0, width]), | |
y = d3.scaleLinear() | |
.domain([0, 365]) | |
.range([height, 0]), | |
z = d3.scaleOrdinal(d3.schemeCategory10); | |
// function for generation of path | |
var line = d3.line() | |
.curve(d3.curveLinear) | |
.x(function(d) { | |
return x(d.date); | |
}) | |
.y(function(d) { | |
return y(d.days); | |
}); | |
d3.csv('Air_Quality_Index_Days.csv', type, function(error, data) { | |
if (error) throw error; | |
var airData = data.columns.slice(1).map(function(id) { | |
// creates an array of objects: | |
// One object for each column name (id) | |
// Contains an id field and a values field | |
// the values field is an object containing | |
// two arrays : date and temperature | |
return { | |
id: id, | |
values: data.map(function(d) { | |
return { | |
date: d.Year, | |
days: d[id] | |
}; | |
}) | |
}; | |
}); | |
console.log(airData); | |
// set x domain | |
x.domain([ | |
d3.min(airData, function(c) { | |
return d3.min(c.values, function(d) { | |
return d.date; | |
}); | |
}), | |
d3.max(airData, function(c) { | |
return d3.max(c.values, function(d) { | |
return d.date; | |
}); | |
}) | |
]); | |
// set up z (fill) domain | |
z.domain(airData.map(function(c) { | |
return c.id; | |
})); | |
// create axis | |
var xAxis = d3.axisBottom() | |
.scale(x); | |
var yAxis = d3.axisLeft() | |
.scale(y); | |
// create paths for each outcome | |
var airQuality = svg.selectAll(".airQuality") | |
.data(airData) | |
.enter().append("g") | |
.attr("class", "airQuality"); | |
airQuality.append("path") | |
.attr("class", "line") | |
.attr("d", function(d) { | |
return line(d.values); | |
}) | |
.style("stroke", function(d) { | |
return z(d.id); | |
}); | |
// Add individual data points | |
svg.selectAll(".aqpoints") | |
.data(airData) | |
.enter().append("g") | |
.attr("class", "aqpoints") | |
.style("fill", function(d) { | |
return z(d.id); | |
}) | |
.selectAll(".point") | |
.data(function(d) { | |
return d.values; | |
}) | |
.enter().append("circle") | |
.attr("class", "point") | |
.attr("r", 4.5) | |
.attr("cx", function(d) { | |
return x(d.date); | |
}) | |
.attr("cy", function(d) { | |
return y(d.days); | |
}) | |
.on("mouseover", function(d) { | |
//calculate position of tooltip | |
var xPosition = parseFloat(d3.select(this).attr("cx")); | |
var yPosition = parseFloat(d3.select(this).attr("cy")) - 20; | |
//Create the tooltip label | |
svg.append("text") | |
.attr("id", "tooltip") | |
.attr("x", xPosition) | |
.attr("y", yPosition) | |
.attr("text-anchor", "middle") | |
.attr("font-family", "sans-serif") | |
.attr("font-size", "11px") | |
.attr("font-weight", "bold") | |
.attr("fill", "black") | |
.text(d.days); | |
}) | |
.on("mouseout", function() { | |
//Remove the tooltip | |
d3.select("#tooltip").remove(); | |
}); | |
// append axis | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", "0.71em") | |
.attr("fill", "#000") | |
.text("Days per Year"); | |
//label each series | |
airQuality.append("text") | |
.datum(function(d) { | |
return { | |
id: d.id, | |
value: d.values[d.values.length - 1] | |
}; | |
}) | |
.attr("transform", function(d) { | |
return "translate(" + (x(d.value.date) - 5) + "," + (y(d.value.days) - 20) + ")"; | |
}) | |
.attr("x", 3) | |
.attr("dy", "0.35em") | |
.style("font", "12px sans-serif") | |
.attr("font-weight", "bold") | |
.attr("fill", function(d) { | |
return z(d.id) | |
}) | |
.text(function(d) { | |
return d.id; | |
}); | |
}); | |
// row data format function | |
function type(d, _, columns) { | |
d.Year = parseTime(d.Year); | |
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c]; | |
return d; | |
} | |
</script> | |
<p></p> | |
<a href="https://www.opendataphilly.org/dataset/air-quality-index-days">Source: Open Data Philly</a> | |
</body> | |
</html> |
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
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.point { | |
stroke: #000; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment