In the previous blog post I showed few examples of data visualization using D3.js. There were multiple examples of choropleth maps, summarizing population, population change, and employment rates data. In this blog post I will try to show step by step guide on how to create similar maps. As an example I am working on New Mexico population data by county. The data was obtained through US Census Bureau, and is available to download straight from their website. The files used in this example are provided at the end of this blog post. Also I’d like to suggest Mike Bostock’s Choropleth example as a guide to mapping. Topojson file creation from Shapefile is not shown in this tutorial. I might write a separate blog post on that topic.
We start by creating the layout of the page with some CSS styling.
<style> .site { display: inline-block; } path { stroke: white; stroke-opacity: 0.7; stroke-width: 0.7; } path:hover { fill-opacity: .7; } </style>
Simple body layout:
<body> <div class="site"> <main class="area"></main> </div> </body>
Next we are importing the needed scripts to be able to run D3.js.
<!-- Loading the d3.v4, d3-scale-chromatic, and topojson libraries --> <script src="http://d3js.org/d3.v4.min.js"></script> <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <script src="http://d3js.org/topojson.v2.min.js"></script>
We start our main script by defining the height and the width of the map:
var width = 500, height = 500;
Constructing a new map object:
var nmPopul = d3.map();
Color variable is created. Using .domain function, we can define the boundaries of the data (population), and using .range() function. we can transform them into the range of colors (in this case – the shades of green):
var color = d3.scaleThreshold() .domain([1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000]) .range(d3.schemeGreens[9]);
Creating and appending the svg1 element to the “area” main class (for map):
var svg1 = d3.select(".area").append("svg") .attr("width", width) .attr("height", height);
Setting a projection and scaling it according to the topojson file we have. You can check the link for more on projections:
var projection = d3.geoAlbersUsa() .scale(width * 9) .translate([width * 1.72, -width/10]);
Creating a new geographic path generator with the specified projection; d3.geoPath takes a topojson info and returns SVG path data based on the projection.
var path = d3.geoPath() .projection(projection);
Adding formatting variable to display comma for thousands separator:
var fCom = d3.format(",");
Importing the data using d3.queue() function.
d3.queue() .defer(d3.json, "nmNMod.json") .defer(d3.csv, "NM-Popul-C.csv", function(d){ nmPopul.set(d.id, +d.popEst2016); }) .await(plotting);
Taking the imported topojson file, appending the path, and filling the data with the corresponding color from the color variable created earlier. Also, appending (“title”) – to show the data information once the mouse is over the particular county:
function plotting(error, data){ if(error) throw error; svg1.selectAll('path') .data(topojson.feature(data, data.objects.cb_2015_new_mexico_county_20m).features) .enter() .append('path') .attr('d', path) .attr("fill", function(d) { return color(d.nmPopul = nmPopul.get(d.properties.GEOID)) }) .append("title") .text(function(d) { return d.properties.NAME + ", pop.: " + fCom(d.nmPopul); }); }
Downloadable content: New Mexico population d3.js sample page New Mexico topojson file New Mexico population by counties