Created
March 15, 2013 18:55
-
-
Save milesgrimshaw/5172167 to your computer and use it in GitHub Desktop.
Obesity In The USA (Octopress Blog Post)
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
--- | |
layout: post | |
title: "Obesity in the USA" | |
date: 2013-03-14 12:59 | |
comments: true | |
categories: | |
--- | |
<!-- Make sure to include D3 first or else the IIFEs won't work. --> | |
<script src="http://d3js.org/d3.v2.js"></script> | |
<script type="text/javascript" src="/Data/obesitystatedata.js"></script> | |
<!-- CSS Styles: --> | |
<div> | |
<style type="text/css"> | |
#states path { | |
stroke: white; | |
} | |
.year { | |
font-size: 3em; | |
} | |
.controls { | |
padding-top: 10px; | |
padding-left: 15; | |
width: 540; | |
text-align: center; | |
font-size: 12px; | |
} | |
.controls span { | |
padding-left: 2px; | |
padding-right: 2px; | |
} | |
.legendtext { | |
font-size: 15px; | |
font-family:"Arial, sans-serif"; | |
font-weight: bold; | |
} | |
</style> | |
</div> | |
<!-- Global Variables and Handlers: --> | |
<!-- Notes: | |
Each Octopress blog post is contained within the div with class '.entry-content'. | |
--> | |
<script type="text/javascript"> | |
//var margin = {top: 40, right: 40, bottom: 40, left: 40}, | |
var width = $('.entry-content').width(); | |
//plus 50 for the height so room for the legend | |
var height = (width/2 + 50); | |
var barwidth = width/2, | |
barheight = height/4, | |
x1 = 200, | |
y1 = 400; | |
var year = 1995; | |
$(window).resize(function() { | |
width = $('.entry-content').width(); | |
}); | |
</script> | |
<div id='chart-obesity'></div> | |
<script type='text/javascript'> | |
//have to move the map up 50 to leave 50 room for the legend | |
var xy = d3.geo.albersUsa() | |
.scale(width) | |
.translate([width/2, height/2 - 50]); | |
var path = d3.geo.path().projection(xy); | |
var yearcontrols = d3.select("#chart-obesity") | |
.append("div") | |
.attr("class", "controls"); | |
var svg = d3.select("#chart-obesity") | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("id", "states"); | |
var statesmap = d3.select("#states"); | |
var data = obesitystatedata; | |
var maxobese = d3.max(data, function (d) | |
{ | |
return Math.max(d["obese"]); | |
}); | |
var minobese = d3.min(data, function (d) | |
{ | |
return Math.min(d["obese"]); | |
}); | |
var lightness = d3.scale.linear().domain([minobese, maxobese]).range([0, 1]); | |
var gradient = statesmap.append("svg:defs") | |
.append("svg:linearGradient") | |
.attr("id", "gradient") | |
.attr("x1", "0%") | |
.attr("y1", "0%") | |
.attr("x2", "100%") | |
.attr("y2", "0%"); | |
for (i=0; i<=1; i+=0.05) { | |
gradient.append("svg:stop") | |
.attr("offset", (i*100)+ "%") | |
.attr("stop-color", colorof(i,lightness)) | |
.attr("stop-opacity", 1); | |
} | |
//Add the legend | |
svg.append('svg:rect') // create a new rectangle for the scale legend | |
.attr("x", width/2 -100) | |
.attr("y", height - 50) | |
.attr('width','200') | |
.attr('height','20') | |
.attr('fill', 'url(#gradient)'); // fill the object using the gradient with the id 'legendgrad' | |
//Labels for the legend | |
svg.append('svg:text') // create a new text area for the label for the starting point of the gradient | |
.attr('class','legendtext') // give the object the id 'minlabel' | |
.attr("x", width/2- 100) | |
.attr("y", height - 54) | |
.attr('text-anchor', 'start') | |
.attr('font-family','Arial') // sets the font family to Arial, for a nicer look | |
.text(minobese + "%"); // the text of the label (our lowest value) | |
svg.append('svg:text') // create a new text area for the label for the ending point of the gradient | |
.attr('class','legendtext') // give the object the id 'maxlabel' | |
.attr('x', width/2 + 100) | |
.attr('y', height - 54) | |
.attr('text-anchor', 'end') // set 'text-achor' to right so that it works right-to-left so that the end of the | |
.text(maxobese + "%") // the text of the label (our maximum value and everything above it) | |
svg.append('svg:text') // create a new text area for the label for the legend | |
.attr('class','legendtext') // give the object the id 'legendlabel' | |
.attr("x", width/2) | |
.attr("y", height-10) | |
.attr('text-anchor', 'middle') // set 'text-achor' to middle so that it distributes the text evenly left and right so that our text remains centered | |
.attr('font-family','Arial') // sets the font family to Arial, for a nicer look | |
.text('Percent of Americans Obese'); // | |
//Add the controls for changing the year and the current year value | |
yearcontrols.append("span") | |
.append("a") | |
.attr("class", "year back") | |
.attr("href", "javascript: yearnext(false);") | |
.text("<<"); | |
var title = yearcontrols.append("span") | |
.attr("class", "year") | |
.text(year); | |
yearcontrols.append("span") | |
.append("a") | |
.attr("class", "year next") | |
.attr("href", "javascript: yearnext(true);") | |
.text(">>"); | |
//Create all the states | |
d3.json("/Data/us-states.json", function (collection) { | |
statesmap.selectAll("path") | |
.data(collection.features) | |
.enter() | |
.append("path") | |
.attr("d", path) | |
.attr("fill", function(d){return colorspec(d,year, lightness)}); | |
}); | |
//FUNCTIONS | |
function colorspec (states, year, lightness){ | |
var level = obesitylevel(states, year); | |
var hue = 0; | |
var l = lightness(level); | |
color = d3.hsl(hue,1,(1-l)); | |
return (color.toString()); | |
} | |
function colorof (i, lightness) { | |
var hue = 0; | |
color = d3.hsl(hue, 1, (1-i)); | |
return (color.toString()); | |
} | |
function obesitylevel (states, year){ | |
var year = year; | |
var data = obesitystatedata; | |
var state = [states.properties.name]; | |
var allstateatyear = data.filter(function(d){return d.year==[year];}); | |
var stateatyear = allstateatyear.filter (function (allstateatyear){return allstateatyear.state==[state];}); | |
var level = stateatyear.map(function(d){return d["obese"];}); | |
return level; | |
} | |
function yearnext(next) { | |
if (next) { | |
year = Math.min(2010, year+1); | |
if (year == 2009) | |
year += 1; | |
statesmap.selectAll("path").attr("fill", function(d){return colorspec(d,year, lightness)}); | |
title.text(year); | |
} | |
else { | |
year = Math.max(1995, year-1); | |
if (year == 1996) | |
year -= 1; | |
statesmap.selectAll("path") | |
.attr("fill", function(d) { return colorspec(d,year,lightness)}); | |
title.text(year); | |
} | |
} | |
document.onkeydown = function(event) { | |
switch(event.keyCode) { | |
case 37: | |
yearnext(false); | |
break; | |
case 39: | |
yearnext(true); | |
break; | |
} | |
}; | |
</script> | |
###Notes: | |
- The motivation for this project was | |
1. To learn D3 | |
2. To learn how to create a D3 visualization in an Octopress blog post | |
3. To improve upon the current CDC graphic for visualizing this data. | |
- The metric being used is the % of people per state that are classified as obese (BMI 30.0+). | |
- The CDC has a [set of powerpoint slides on their website](http://www.cdc.gov/obesity/data/adult.html) that loops through the years and color codes states by obesity level. I felt that D3 would offer a chance to improve on the graphic by making it more interactive, and also using a linear color gradient as opposed to more significant color changes each 5%. | |
- All the data was collected using [this CDC tool](http://apps.nccd.cdc.gov/BRFSS/) that provides the percent of obese individuals per state since 1995. I downloaded individual CSV files for each year and then combined them into one CSV for 1995-2010. I then used [this data converted](http://www.shancarter.com/data_converter/index.html) to convert the CSV into JSON-properties that I could then access. | |
- If you are interested in how to create D3 graphics in an Octopress blog post I have posted the raw code for this post in a [gist here](). It isn't the cleanest, but it works and if you have feedback please drop me a comment! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment