Choropleth map with quantile-based stepped colorscale and filter option

Hi everyone,

I often find that quantile-based scales work better than linear ones when visualizing choropleth map data. (After all, particularly high or low values can easily skew a linear range.)

Therefore, I put together a county population-growth dashboard that allows growth rates to be viewed in either percentile-based or quantile-based form. The dashboard also lets users determine the starting and ending years for population growth calculations and set a minimum population size; the dashboard’s JavaScript code will then calculate new colorscales accordingly.

The dashboard also shows how to use Plotly’s hovertemplate argument, together with its customdata argument, to create custom tooltips that show data both from the map’s underlying GeoJSON data and the population-growth table that it imports.

Although I’ve enjoyed using Danfo.js for underlying data manipulation, that library hasn’t been updated in a little while, so I used d3-array for certain data-related tasks instead.

To view the project’s underlying code and see how the data was retrieved, feel free to visit its GitHub repository. All content has been made available under the MIT license (though the underlying datasets, which come from the US Census, are in the public domain).

Here are a few screenshots:

  1. Default view:

2. Filtered view showing only counties with 100K+ residents in 2024: (Note that the colorscale got updated to reflect this filtered dataset.)

  1. Linear scale: (Note how a few outliers caused the scale to become much more muted)

I hope you find this project’s code useful in your own work!

Really cool project, @KBurchfiel .
Is this the file that builds the choropleth map in Plotly.js?

I really like the colors chosen and how easy it is to visualize the growth/decline in population. Is this project done or were you planning to add more graphs?

Thank you, @adamschroeder ! Yes, that’s the HTML file that contains all of the code for the maps. It would have been cleaner to separate out the HTML, CSS, and JavaScript into separate files, but this approach will do for now :slight_smile:

I have now updated the dashboard to allow for relatively fast percentile-rank calculations; these ranks have been added to each county’s tooltip. In addition, the dashboard displays an error when a user selects an excessively-high minimum county population value.

I don’t have any other updates planned in the near future, but this dashboard might serve as a template for future mapping projects :slight_smile: (I will also try to update the population estimates shown within the dashboard once a new set of ACS5 data comes out. The scripts I used for retrieving this Census data can be found at county_growth_trends/data_retrieval at main · kburchfiel/county_growth_trends · GitHub .)

OK @adamschroeder, one additional update: The previous code, while functional, was a bit complex for my liking, since it involves creating a discretized continuous colorscale, then specifying numerical codes for each bin that lie at the midpoint of each discrete range. If I’m not careful, it would be easy to mess up the specification of this colorscale and thus display an incorrect mapping between colors and values.

Therefore, I’ve now implemented a simpler approach that involves (1) assigning a bin label (e.g. “18 to 36”) to each row of my array, then (2) rendering the map by using a for loop to plot each label’s rows. This eliminates the need to specify codes on a 0-1 scale for each bin, thus offering a more direct link between colors and value bins. (The code that implements this approach can be found here.)

Although the map takes a little longer to render within this new approach, perhaps as a result of the additional filter operations needed to render each set of bins, it’s now possible for users to show or hide specific bins–which makes it easier to identify particularly fast-growing regions.

Here’s a look at the new map: (Notice that each bin entry now has a separate box of its own.)

If I want to see only the regions with the highest population growth or decline, I can deselect all but the first and last box, resulting in the following map:

This type of filter operation wasn’t possible within the original continuous-colorscale setup. However, the map that incorporates that setup is still available at this link.

The new map also has a bit of an accidental animation effect as a result of each bin’s corresponding rows getting loaded in one by one. I’m not sure whether this is a ‘bug’ or a ‘feature,’ but I’m leaning towards the latter for now!

Finally, it’s neat how Plotly automatically splits the legend into two rows on narrower screens (such as cell phones):

I think I’m more or less finished with this project for now, but I’m sure that this template will prove useful for future mapping tasks that I take on!

@KBurchfiel I really like how we can now deselect certain bins through the legend. By turning a specific category on and off several times, it becomes a lot clearer what sections of the US are at stake. I’ve written you a DM to explore various ways to showcase this map to more people.