Skip to content

Instantly share code, notes, and snippets.

@rgdonohue
Last active April 13, 2016 16:38
Show Gist options
  • Save rgdonohue/d21239a488b5ab15dbbdf7567db1b086 to your computer and use it in GitHub Desktop.
Save rgdonohue/d21239a488b5ab15dbbdf7567db1b086 to your computer and use it in GitHub Desktop.
Dynamic Classification of CartoDB Choropleth Map

This technique demonstrates calculating class ranges (i.e. breaks) for dynamically coloring a choropleth requested from data hosted on CartoDB.

The solution requires two requests:

  1. first for the raw data so the full range of the data can be classified (here using the ckmeans clustering method from Simple Statistics)
  2. then to request the tiles using the generated cartoCSS rules

Data are percentages of uninsured Americans in 2015. Darker blue indicates higher percentage.

Legend comes next.

<!DOCTYPE html>
<html>
<head>
<title>Dynamic Classification of CartoDB Choropleth Map</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
background: #3d3d3d;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simple-statistics/1.0.1/simple_statistics.min.js"></script>
<script>
// instantiate our map
var map = new L.Map("map", {
center: [-6,-2],
zoom: 4.5
});
// request the (non-geometry) data first to calculate class ranges
$.getJSON('https://rgdonohue.cartodb.com/api/v2/sql?format=JSON&q=SELECT * FROM uninsured_adults_county', function(data) {
// push all the values into an array
var values = [];
data.rows.forEach(function(row,i) {
if(row.uninsured) {
values.push(row.uninsured);
}
});
// create array of range clusters
var clusters = ss.ckmeans(values, 7);
// pull out the low and high values from each cluster
var ranges = clusters.map(function(cluster){
return [cluster[0],cluster.pop()];
});
makeMap(ranges);
});
function makeMap(ranges) {
var colors = ['#eff3ff','#c6dbef','#9ecae1','#6baed6', '#4292c6','#2171b5','#084594'];
// build the cartoCSS
var cartoCSSRules = '#uninsured_adults_county{' +
'polygon-opacity: 0.8;' +
'polygon-comp-op: lighten;' +
'line-color: #FFF;' +
'line-width: 0.5;' +
'line-opacity: 1;' +
'}';
// loop backwards, high to low
for(var i = ranges.length; i--;) {
var value = ranges[i][1],
color = colors[i];
// build the individual rules
var thisRule = '#uninsured_adults_county [ uninsured <= ' +
value + '] { polygon-fill: ' + color + ';}'
// add them to the cartoCSS
cartoCSSRules += thisRule;
}
// source object for requesting the tiles
var countiesLayers = {
user_name: 'rgdonohue',
type: 'cartodb',
sublayers: [{
sql: "SELECT ST_Transform(the_geom, 2163) AS the_geom_webmercator, cartodb_id, uninsured FROM uninsured_adults_county WHERE statefp != '02' and statefp != '15' and statefp != '72'",
cartocss : cartoCSSRules
}, {
sql: "SELECT ST_Scale(ST_Translate(ST_Transform(the_geom, 102007),-1600000,-2300000),1,1) AS the_geom_webmercator, cartodb_id, uninsured FROM uninsured_adults_county WHERE statefp = '15'",
cartocss : cartoCSSRules
}, {
sql: "SELECT ST_Scale(ST_Translate(ST_Transform(the_geom, 102006),-3563330,-3883900),.7,.7) AS the_geom_webmercator, cartodb_id, uninsured FROM uninsured_adults_county WHERE statefp = '02'",
cartocss : cartoCSSRules
}]
};
cartodb.createLayer(map, countiesLayers)
.addTo(map)
.done(function(layers) {
// blam
})
.error(function(err) {
console.log("Oopsie Poopsie: " + err);
});
} // end makeMap()
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment