I have been asked by my wife to take data about the California Beauty license count and turn it into a choropleth map. This is a map that uses regional colors to indicate different values. In my case the map will show how many licenses were issued in the state of California Board of Barbering and Cosmetology (BBC) broken down by county. Here is an example of a choropleth map from scribblelive.com

It is a trivial task in a modern Business Intelligence application like Tableau or Power BI, but those cost money that I didn't want to spend on this. I love my wife more than life itself, but this project isn't going to be reimbursed by anyone. So I dug around and have determined that D3.js is the best tool for the job. The thing that got me really hung up was my poor web programming skills. I started this in late August and have only just completed it to the point where it is generally usable.

The project has these basic steps:

1. Save data as JSON file

2. Get county boundaries in JSON file.

3. Convert county boundaries into a GeoJSON file.

4. If necessary, reduce the size of the GeoJSON file using a service like https://mapshaper.org/.

In the program/web page:

1. Load the BBC data into memory

2. Render a map of California with the county boundaries

3. Color each county according to the number of a type of license or the total number of licenses

I also wanted to keep my code isolated from the web page as much as possible and to not slow the rendering because of waiting for files to load. I should mention that this is exactly opposite of what was recommended by someone with much more JavaScript experience than I. I made those choices because in general they are best practices in software development. It paid of in the end, but I had to really stay fast on keeping them separate. Especially when I was so tempted to just put it all into one file because the references to the script and data files were wrong. You can look at the report here. When I first uploaded this report it took about 5-10 seconds to render. This isn't the most awesome virtual server in the world, but it should be quicker than that. After I ran the GeoJSON through Map Shaper I was able to cut the time down to 2-3 seconds.

There are some things that still aren't done. There is a great deal of skew in the data, on average about 4.5 for every license type. A skew greater than +1 or less than -1 is considered large. The reason for this is that 4 or 5 counties hold most of the licenses in every category. I used code to keep a list of counties to not include in the range for the colors, they end up getting the high color, and leaving the rest to lay where they are.

Lets look at the code. First the web page. A note that my choice for the webpage is not necessarily the best D3 way to do it. Other people have a lot less specified HTML tags. I kept this because I wanted to sharpen my meager HTML skills. Anyway here is some boiler plate stuff and the script calls:

<!DOCTYPE html>
<meta charset="utf-8">

<html>
<head>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script src="scripts/drawmap.js"></script>

</head>

 The last script tag is to all the JavaScript code I wrote. Note that I am using V5. I say this because there are so many resources for many different versions of D3. v3 is a popular version, but requires more code to make things work. So the last part of this is the HTML describing the page itself. It has the body, the root of the HTML DOM. It responds to a single event onload to create the map. Note that it does not run until after the entire page is loaded. A minor point for this page, but if you have a lot of stuff on your page it could take some time for your map to load. If I were smarter I would start the asynchronous data pulls when the page starts loading, and then draw the map when it is completely loaded.

<body onload="drawMap()">
 
<form id="licenseType">
Which license would you like to view:
<select onchange="drawMap()">
<option selected>All</option>
<option>Barber</option>
<option>Cosmetology</option>
<option>Electrology</option>
<option>Esthetician</option>
<option>Manicure</option>
<option>Establishment</option>
<option>Mobile Unit</option>
</select>
</form>
<svg id="bbc_ca" width="750" height="900"></svg>
 
</body>
</html>

Another modification I would consider is removing all the options for the drop down except the "All" option and populate the list from the data. Lastly there is the SVG tag that will hold our map. I have thought about adding a table to the left of the map showing all the licenses for whatever county is being hovered over. In the next article I'll go over the JavaScript code and hopefully provide you with enough clarity that you could do a similar project.

Like it on Facebook, +1 on Google, Tweet it or share this article on other bookmarking websites.