Skip to content

Instantly share code, notes, and snippets.

@bdilday
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bdilday/ac943080045043d53971 to your computer and use it in GitHub Desktop.
Save bdilday/ac943080045043d53971 to your computer and use it in GitHub Desktop.

A visualization of some data from the 2010 U.S. Census. This was created for the University of Illinois Coursera class on data visualization.

My submission uses data on the population and area of US states, based on the 2010 census, and was obtained from the census.gov website. The data are displayed using bar charts built with d3 and the visualization includes an interactive sorting feature and a text display if you hover the mouse over a bar. Because area and volume are less effective in communicating quantitative differences than length, I was interested in the idea of using length to display area or volume. I applied the guideline of using desaturated colors for the fills of the bars. I included density as a sorting option, but didn't display it as a bar since it is computable from population and area. This is motivated by Edward Tufte's guidelines of removing redundent elements of the visualization.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var sort_select = 'state';
var margin = {top: 20, right: 40, bottom: 80, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = {};
y['area'] = d3.scale.linear()
.range([height, 0]);
y['pop2010'] = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#8a89a6", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y['pop2010'])
.orient("left")
.tickFormat(d3.format(".2s"));
var yAxis_right = d3.svg.axis()
.scale(y['area'])
.orient("right")
.tickFormat(d3.format(".2s"));
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 + ")")
;
var xi = 85;
var fsz = 12;
var yi = 10;
var dyi = 15;
var fl = '#111111';
var info_display_1 = svg.append('text')
.attr('id', 'info_display_1')
.attr('x', xi)
.attr('y', yi + 0*dyi)
.style('font-size', fsz + "px")
.style('opacity', 1)
.style('fill', fl)
.style('background-color', '#000')
;
var info_display_2 = svg.append('text')
.attr('id', 'info_display_2')
.attr('x', xi)
.attr('y', yi + 1*dyi)
.style('font-size', fsz + "px")
.style('opacity', 1)
.style('fill', fl)
.style('background-color', '#000')
;
var info_display_3 = svg.append('text')
.attr('id', 'info_display_3')
.attr('x', xi)
.attr('y', yi + 2*dyi)
.style('font-size', fsz + "px")
.style('opacity', 1)
.style('fill', fl)
.style('background-color', '#000')
;
var info_display_4 = svg.append('text')
.attr('id', 'info_display_4')
.attr('x', xi)
.attr('y', yi + 3*dyi)
.style('font-size', fsz + "px")
.style('opacity', 1)
.style('fill', fl)
.style('background-color', '#000')
;
var title = svg.append('text')
.text("US States: 2010 Census")
.attr('id', 'info_title')
.attr('x', 350)
.attr('y', 0)
.style('font-size', "18px")
.style('opacity', 1)
.style('fill', fl)
.style('background-color', '#000')
;
function sort_data(data, key) {
if (key == sort_select) {
sort_select = key;
return data.reverse();
}
sort_select = key;
sdata = _.sortBy(data, key);
if (key=='state')
return sdata;
return sdata.reverse();
};
d3.csv("state_area_pop.csv", function(error, data) {
data.forEach(function(d) {
d.area = parseFloat(d.area);
d.pop2010 = parseInt(d.pop2010);
});
var cols = ['area', 'pop2010']
data.forEach(function(d) {
d.values = cols.map(function(name) {
return {'name': name, 'value': +d[name]};
});
});
data.forEach(function(d) {
d.density = d.pop2010/d.area;
});
sdata = sort_data(data, 'state');
console.log('sdata', sdata);
x0.domain(data.map(function(d, i) { return i; }));
x1.domain(cols).rangeRoundBands([0, x0.rangeBand()]);
y['pop2010'].domain([0, 38000000]);
y['area'].domain([0, 680000]);
var xa = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.text(function(d, i) {
return sdata[i].state.replace('_', ' ').replace('_', ' ');
})
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)" )
.attr('font-size', '8px')
.attr('class', 'xaxis_label')
;
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text('Population')
;
svg.append("g")
.attr("class", "y axis")
.call(yAxis_right)
.attr("transform", "translate(" + width + " ,0)")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -16)
.attr("y", -16)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text('Area (sq. miles)')
;
function updatePlot(sdata, key) {
console.log('updating the plot');
old_keys = {}
sdata.forEach(function(d, i) {
old_keys[d.state] = i;
});
keys = {};
sdata = sort_data(sdata, key);
sdata.forEach(function(d, i) {
keys[d.state] = i;
});
state.transition()
.attr("transform", function(d, i) {
return "translate(" + x0(i) + ",0)";
})
;
var k = 'area';
rect[k].transition().duration(2000)
.attr("x", function(d, i) {
return x0(keys[d.state]) + x1(k);
})
;
var k = 'pop2010';
rect[k].transition().duration(2000)
.attr("x", function(d, i) {
return x0(keys[d.state]) + x1(k);
})
;
xa.transition(2000)
.text(function(d, i) {
return sdata[i].state.replace('_', ' ').replace('_', ' ');
});
}
var state = svg.selectAll(".state")
.data(sdata)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d, i) { return "translate(" + x0(i) + ",0)"; });
function info_text(datum) {
var fmt = d3.format('.1f');
d3.selectAll('#info_display_1')
.text('state: ' + datum.state.replace('_', ' ').replace('_', ' ') )
.transition()
.duration(100)
.style('opacity', 1);
d3.selectAll('#info_display_2')
.text('population: ' + datum.pop2010)
.transition()
.duration(100)
.style('opacity', 1);
d3.selectAll('#info_display_3')
.text('area (sq.mi): ' + datum.area)
.transition()
.duration(100)
.style('opacity', 1);
d3.selectAll('#info_display_4')
.text('density (per sq.mi): ' + fmt(datum.density))
.transition()
.duration(100)
.style('opacity', 1);
};
function info_text_off() {
d3.selectAll('#info_display_1')
.transition()
.duration(100)
.style('opacity', 0)
;
d3.selectAll('#info_display_2')
.transition()
.duration(100)
.style('opacity', 0)
;
d3.selectAll('#info_display_3')
.transition()
.duration(100)
.style('opacity', 0)
;
d3.selectAll('#info_display_4')
.transition()
.duration(100)
.style('opacity', 0)
;
};
var rect = {};
var k = 'area';
rect[k] = svg.selectAll(".rect_area")
.data(sdata)
.enter().append("rect")
.attr('class', 'rect_area')
.attr("width", x1.rangeBand())
.attr("x", function(d, i) {
return x0(i) + x1(k); })
.attr("y", function(d, i) {
return y[k](d[k]); })
.attr("height", function(d) {
return height - y[k](d[k]); })
.style("fill", function(d) { return color(k); })
.on('mouseover', function(d, i) {
info_text(d);
;})
.on('mouseout', function(d, i) {
info_text_off();
})
;
var k = 'pop2010';
rect[k] = svg.selectAll(".rect_pop2010")
.data(sdata)
.enter().append("rect")
.attr('class', 'rect_pop2010')
.attr("width", x1.rangeBand())
.attr("x", function(d, i) {
return x0(i) + x1(k); })
.attr("y", function(d, i) {
return y[k](d[k]); })
.attr("height", function(d) {
return height - y[k](d[k]); })
.style("fill", function(d) { return color(k); })
.on('mouseover', function(d, i) {
info_text(d);
;})
.on('mouseout', function(d, i) {
info_text_off();
})
;
var sorteys = [{ 'k': 'name', 'v': 'state'},
{ 'k': 'pop.', 'v': 'pop2010'},
{ 'k': 'area', 'v': 'area'},
{ 'k':'density', 'v':'density'}
];
var sort_options = svg.selectAll('.sort_options')
.data(sorteys)
.enter().append('g')
.attr('class', 'sort_options')
.attr('transform', function(d, i) { return "translate(0," + i * 20 + ")"; })
;
sort_options.append('text')
.text(function(d) {return d.k;})
.style('text-align', 'right')
.attr("x", width - 60)
.attr('y', function(d, i) {
return 80; //parseInt(i + 70);
})
.attr("width", 40)
.attr("height", 12)
.style("fill", '000')
.style('cursor', 'pointer')
.on('click', function(d, i) {
updatePlot(sdata, d.v);
})
;
svg.append('text')
.text('Sort By')
.attr('x', width - 60)
.attr('y', 60);
var legend = svg.selectAll(".legend")
.data(cols.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 40)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 46)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
state area pop2010
Maine 35379.74 1328361
New_Hampshire 9349.16 1316470
Vermont 9616.36 625741
Massachusetts 10554.39 6547629
Rhode_Island 1544.89 1052567
Connecticut 5543.41 3574097
New_York 54554.98 19378102
New_Jersey 8722.58 8791894
Pennsylvania 46054.34 12702379
Ohio 44825.58 11536504
Indiana 36419.55 6483802
Illinois 57913.55 12830632
Michigan 96713.51 9883640
Wisconsin 65496.38 5686986
Minnesota 86935.83 5303925
Iowa 56272.81 3046355
Missouri 69706.99 5988927
North_Dakota 70698.32 672591
South_Dakota 77115.68 814180
Nebraska 77347.81 1826341
Kansas 82278.36 2853118
Delaware 2488.72 897934
Maryland 12405.93 5773552
District_of_Columbia 68.34 601723
Virginia 42774.93 8001024
West_Virginia 24230.04 1852994
North_Carolina 53819.16 9535483
South_Carolina 32020.49 4625364
Georgia 59425.15 9687653
Florida 65757.70 18801310
Kentucky 40407.80 4339367
Tennessee 42144.25 6346105
Alabama 52420.07 4779736
Mississippi 48431.78 2967297
Arkansas 53178.55 2915918
Louisiana 52378.13 4533372
Oklahoma 69898.87 3751351
Texas 268596.46 25145561
Montana 147039.71 989415
Idaho 83568.95 1567582
Wyoming 97813.01 563626
Colorado 104093.67 5029196
New_Mexico 121590.30 2059179
Arizona 113990.30 6392017
Utah 84896.88 2763885
Nevada 110571.82 2700551
Washington 71297.95 6724540
Oregon 98378.54 3831074
California 163694.74 37253956
Alaska 665384.04 710231
Hawaii 10931.72 1360301
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment