Visualizing 2012 census estimates using CartoDB and Leaflet

I’ve been tinkering around with some new mapping tools lately, and figured I’d put them to good use by displaying the 2011-2012 population estimates released last week by the U.S. Census Bureau. The inherently geographical nature of the census makes it a data set just begging to be mapped.

Rather than the de facto Google Maps JavaScript API V3, I decided to go with CartoDB and Leaflet to see what I could produce.

As I mentioned in a recent post, CartoDB offers an excellent Fusions-esque interface, although it allows for far less front-end customization and requires more beneath the hood programming. Nonetheless, CartoDB can make pretty maps right out of the box, which you can then fully customize using the CartoDB API and basic SQL statements. There’s one caveat, however: The service only allows you to upload 5 tables for free. That could be a dealbreaker for cash-strapped news organizations and freelance data journalists.

Anyhow, I downloaded a .zip shapefile package of all 159 Georgia counties from the U.S. Census Bureau, then brought the package into CartoDB using the service’s default upload interface. Using Excel, I calculated the percent change from the most recent population estimates to last year’s estimates. I then added the resulting values as a column in my CartoDB table, which you can see here.

After playing a bit with the API, I was able to format a diverging chloropleth map from my table with the following style parameters, written using 0to255 to ensure an equidistant color scheme:

#statewidepop {
   line-color:#FFFFFF;
   line-width:1;
   line-opacity:0.52;
   polygon-opacity:1;
}
#statewidepop [percent_change<=5.5] {
   polygon-fill:#558740
}
#statewidepop [percent_change<=4] {
   polygon-fill:#609948
}
#statewidepop [percent_change<=3] {
   polygon-fill:#6AA84F
}
#statewidepop [percent_change<=2.25] {
   polygon-fill:#BECFA8
}
#statewidepop [percent_change<=1.5] {
   polygon-fill:#D0D8BB
}
#statewidepop [percent_change<=0.75] {
   polygon-fill:#B8CCA1
}
#statewidepop [percent_change<=0.3] {
   polygon-fill:#D9DCC4
}
#statewidepop [percent_change<=0] {
   polygon-fill:#D3BAAF
}
#statewidepop [percent_change<=-0.5] {
   polygon-fill:#E7D1C5
}
#statewidepop [percent_change<=-1] {
   polygon-fill:#D8A696
}
#statewidepop [percent_change<=-2] {
   polygon-fill:#C36E59
}
#statewidepop [percent_change<=-3] {
   polygon-fill:#BC5942
}
#statewidepop [percent_change<=-4] {
   polygon-fill:#B34027
}
#tl_2009_13_county[percent_change<=-5] {
   polygon-fill:#AB2B10
}

Check out the resulting map:

The map above shows the percent change in population from July 2010 to July 2011 in all 159 Georgia counties, as estimated by the U.S. Census Bureau. The darker the green, the higher the positive percent change. The darker the red, the higher the negative percent change. Click on a county to see its percent change.

Pretty nice, huh? But what if I want to customize the style of the pop-up windows or perform more advanced functions like creating custom image markers or switching between layers? That’s where Leaflet, an open-source JavaScript library, comes in handy.

Using the Leaflet library

The map above displays the estimated percent change in population of various midstate counties between July 2011 and July 2012. The greener the county, the higher its percent increase. The deeper red the county, the higher its percent decrease. Click on a county to see more precise totals, or select a group from the dropdown in the top right corner for a breakdown of the population changes by race.

To get a wider range of flexibility, I called up a segment of the statewide data – the counties within the Macon/Warner Robins metropolitan area – using the Leaflet javascript. Leaflet allows you to reference layers from CartoDB or Google Maps from within its API, making integration a breeze. All you have to do is reference a few lines of code and your CartoDB data will appear as a layer on your Leaflet map automagically. But even on its own, Leaflet is pretty robust, especially for being so lightweight.

In the map above, I took the county shapefile package from earlier, converted it to GeoJSON using QGis, then, following these parameters, called up the GeoJSON data for the selected counties using the Leaflet script. For the underlying map tiles, I created a custom style using Cloudmade, then referenced it using my API key and the following line of script:

var cloudmade = new L.TileLayer('http://{s}.tile.cloudmade.com/41fc7e18cef34d6fb34756efd8240787/63501/256/{z}/{x}/{y}.png',

Because I also wanted to show a breakdown of the data by race for the same geography, I added in a custom control menu that allows the user to switch between layers for easy comparison. In addition, I styled the popup to my liking, with green and red values to connote increase and decrease.

From there, I was able to add in the additional data sets of population change by race. For each demographic group, I created a corresponding layer group. Each layer group contained the data as well as the appropriate styles and colors. See the source code below:

var totalLayer = new L.LayerGroup();

citiesLayer.addLayer(geojsononeLayer)
           .addLayer(geojsontwoLayer)
           .addLayer(geojsonthreeLayer)
           .addLayer(geojsonfourLayer)
           .addLayer(geojsonfiveLayer)
           .addLayer(geojsonsevenLayer)
           .addLayer(geojsoneightLayer);

var whiteLayer = new L.LayerGroup();

whiteLayer.addLayer(geojsononewhiteLayer)
           .addLayer(geojsontwowhiteLayer)
           .addLayer(geojsonthreewhiteLayer)
           .addLayer(geojsonfourwhiteLayer)
           .addLayer(geojsonfivewhiteLayer)
           .addLayer(geojsonsevenwhiteLayer)
           .addLayer(geojsoneightwhiteLayer);
var blackLayer = new L.LayerGroup();

blackLayer.addLayer(geojsononeblackLayer)
           .addLayer(geojsontwoblackLayer)
           .addLayer(geojsonthreeblackLayer)
           .addLayer(geojsonfourblackLayer)
           .addLayer(geojsonfiveblackLayer)
           .addLayer(geojsonsevenblackLayer)
           .addLayer(geojsoneightblackLayer);

var asianLayer = new L.LayerGroup();

asianLayer.addLayer(geojsononeasianLayer)
           .addLayer(geojsontwoasianLayer)
           .addLayer(geojsonthreeasianLayer)
           .addLayer(geojsonfourasianLayer)
           .addLayer(geojsonfiveasianLayer)
           .addLayer(geojsonsevenasianLayer)
           .addLayer(geojsoneightasianLayer);

var otherLayer = new L.LayerGroup();

otherLayer.addLayer(geojsononeotherLayer)
           .addLayer(geojsontwootherLayer)
           .addLayer(geojsonthreeotherLayer)
           .addLayer(geojsonfourotherLayer)
           .addLayer(geojsonfiveotherLayer)
           .addLayer(geojsonsevenotherLayer)
           .addLayer(geojsoneightotherLayer);

map.addLayer(citiesLayer);

var overlayMaps = {
    "Total Population": citiesLayer,
    "White": whiteLayer,
    "Black": blackLayer,
    "Asian": asianLayer,
    "Other/Mixed": otherLayer
};

var layersControl = new L.Control.Layers(overlayMaps);

map.addControl(layersControl);

All of this was accomplished using the built-in components of the Leaflet JavaScript API and only an hour or so of data analysis in Excel. Next goal? Adding mouseover capabilities.

 

7 Comments Visualizing 2012 census estimates using CartoDB and Leaflet

    1. Carl V. Lewis

      Thanks, Loic. Will check it out – would be a good playground as I figure out CartoDB’s full range of functionality.

      Reply
  1. Pingback: Making the case for hover interactions in maps | Carl V. Lewis

Leave a Reply