Skip to content

Instantly share code, notes, and snippets.

@milesgrimshaw
Created March 15, 2013 18:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milesgrimshaw/5172167 to your computer and use it in GitHub Desktop.
Save milesgrimshaw/5172167 to your computer and use it in GitHub Desktop.
Obesity In The USA (Octopress Blog Post)
---
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