l’Hexagone in hexagons: geospatial data with Uber H3 and Folium

Jens Andersson
4 min readMar 22, 2021

--

BattleTech board game; image from now-defunct otakuspace.com

I don’t think I need to sell you the concept of hexagons. They are just great, and always have been. Among the reasons: they tile the plane, can be any size you need, have consistent area (I’m looking at you, zipcodes) and have 6 neighbours the same distance from each other. No sqrt(2)-because-we-diagonals-are-so-special nonsense.

Be aware: this article was written for H3 v3.7.7, before the breaking API changes of h3-py v4.x. Use pip install h3==3.7.7 or modify the API calls accordingly!

In a pinch, just truncating latitude and longitude to a certain number of decimals can work, but you will soon start kicking yourself and create workarounds for that irregular-sized grid headache you just created.

Battle Isle on the Amiga; image from lemonamiga.com.

However, working out how hexagons should be placed to cover Earth is not something you want to do over and over. Fortunately, Uber’s H3 library comes to the rescue. It provides you with utility functions to map from <latitude, longitude> to <hex ID>, where hex ID is a compact 64-bit number which encodes both the location and the size of the cell.

H3: Uber’s Hexagonal Hierarchical Spatial Index

Abdullah Kurkcu’s blog post about H3 finally got me going with trying it out, but there were a couple of problems (perhaps older library versions?) in the code snippets that prevented it from working out for me. Still, this was a very good start.

For a little example, I reached for the convenient dataset provided by Arthur Charpentier covering French communes and their population numbers.

Visualizing your geospatial data using hexagons takes just a few simple steps:

  1. Add a hex ID wherever you have latitudes and longitudes.
  2. Aggregate your data based on your hex IDs.
  3. Plot your hexagons in a map view, transforming your hex IDs into their actual geometric shapes as needed.

Step 1 is as simple as it sounds (here with a pandas dataset):

geo_to_h3 maps latitude and longitude to a 64-bit hex cell ID.

Step 2 is also simple:

Once you have hex cells, you can aggregate data into them easily.

And then there is step 3. I’ll be honest with you: I lied about all steps being simple. This step is pretty much the reason I even made this blog post. I started out with the helper functions from Abdullah’s blog post, fixed the issues I found and made some changes to make it more convenient (at least for me) to use. Still, this block is just a few helper functions and you don’t need to repeat them for every chart. Alternatively, you can extract the goodies you need for your own versions. (Complete version with all required imports available at the end of the page.)

And that’s it!

l’Hexagone in hexagons, as promised. Colour reflects percentile of cell population.

If this can be accomplished in an easier way, without those helper functions, please do let me know. I am not tied to the Folium maps, if that helps.

Your mileage may vary, and if it does — and by “vary”, I mean that your cells are pretty much all the same colors — my advice to you is to transform your value range. Above, I have used population percentiles, which of course ensures full use of the colour range, because the actual raw data (below) has outliers in the Paris region with a population that is a lot higher than any other part of France; hexagons or not.

This is technically the “correct” chart, but it is not the one I wanted. Colour reflects cell population.

In case you wonder why we need all of those little hexagons when most of France could be covered in much larger ones, the next one is for you. H3 provides the ability of mapping to larger hexagons (“compacting”) in a reversible way, by ignoring that hexagons do not have perfect child containment (one of their few flaws). This results in some gaps in an aggregated view but it looks pretty cool anyway.

This map does not represent anything meaningful, but it illustrates the lack of perfect child containment.

Full Jupyter notebook for the charts above available here.

Be aware: this article was written for H3 v3.7.7, before the breaking API changes of h3-py v4.x. Use pip install h3==3.7.7 or modify the API calls accordingly!

I will resist the urge to link to the excellent Hexagons are the Bestagons (oh no, I failed!) and instead end with a favourite video among those covering H3 from Uber Engineering themselves:

If you have suggestions on how to improve or simplify the above, please let me know. One thing I am missing is a colour legend, but it seems tricky to add that to Folium maps (and the ways I have tried did not work). Also, it would be great if I could get tooltip-like numeric info for individual hex cells.

--

--

Jens Andersson
Jens Andersson

Written by Jens Andersson

Solution Architect at WirelessCar

Responses (1)