How to convert shapefile/geojson to hexagons using uber h3 in python?

2024/9/30 9:30:41

I want to create hexagons on my geographic map and want to preserve the digital boundary specified by the shapefile/geojson as well. How do I do it using uber's h3 python library?

I'm new to shapefiles or any other geographic data structures. I'm most comfortable with python.

Answer

tl;dr

For convenience, you can use H3-Pandas.

import geopandas as gpd
import h3pandas# Prepare data
gdf = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
gdf = gdf.loc[gdf['continent'].eq('Africa')]
gdf['gdp_md_per_capita'] = gdf['gdp_md_est'].div(gdf['pop_est'])
resolution = 4# Resample to H3 cells
gdf.h3.polyfill_resample(resolution)

africa-hexagons

Full description

Use cases like this are precisely why I wrote H3-Pandas, an integration of H3 with Pandas and GeoPandas.

Let's use the naturalearth_lowres dataset included in GeoPandas to demonstrate the usage.

import geopandas as gpd
import h3pandaspath_shapefile = gpd.datasets.get_path('naturalearth_lowres')
gdf = gpd.read_file(path_shapefile)

Let's also create a numeric column for plotting.

gdf = gdf.loc[gdf['continent'].eq('Africa')]
gdf['gdp_md_per_capita'] = gdf['gdp_md_est'].div(gdf['pop_est'])
ax = gdf.plot(figsize=(15, 15), column='gdp_md_per_capita', cmap='RdBu')
ax.axis('off')

africa

We will use H3 resolution 4. See the H3 resolution table for more details.

resolution = 4  

We can add H3 hexagons using the function polyfill. This method adds a list of H3 cells whose centroid falls into each polygon.

gdf_h3 = gdf.h3.polyfill(resolution)
print(gdf_h3['h3_polyfill'].head(3))1     [846aca7ffffffff, 8496b5dffffffff, 847b691ffff...
2     [84551a9ffffffff, 84551cdffffffff, 8455239ffff...
11    [846af51ffffffff, 8496e63ffffffff, 846a803ffff...
Name: h3_polyfill, dtype: object

If we want to explode the values horizontally (ending up with as many rows as there are H3 cells), we can use the parameter explode

gdf_h3 = gdf.h3.polyfill(resolution, explode=True)
print(gdf_h3.head(3))pop_est continent      name iso_a3  gdp_md_est  \
1  53950935    Africa  Tanzania    TZA    150600.0   
1  53950935    Africa  Tanzania    TZA    150600.0   
1  53950935    Africa  Tanzania    TZA    150600.0   geometry  gdp_md_per_capita  \
1  POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...           0.002791   
1  POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...           0.002791   
1  POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...           0.002791   h3_polyfill  
1  846aca7ffffffff  
1  8496b5dffffffff  
1  847b691ffffffff  

We can then utilize the method h3_to_geo_boundary to obtain the geometries for the H3 cells. It expects that the index already has the H3 cell ids.

gdf_h3 = gdf_h3.set_index('h3_polyfill').h3.h3_to_geo_boundary()

We can now plot the result

ax = gdf_h3.plot(figsize=(15, 15), column='gdp_md_per_capita', cmap='RdBu')
ax.axis('off')

africa-hexagons

H3-Pandas actually has convenience function that performs all this at once: polyfill_resample

gdf_h3 = gdf.h3.polyfill_resample(resolution)
ax = gdf_h3.plot(figsize=(15, 15), column='gdp_md_per_capita', cmap='RdBu')
ax.axis('off')

africa-hexagons

https://en.xdnf.cn/q/71102.html

Related Q&A

Python mypy: float and int are incompatible types with numbers.Real

I am new to Pythons static typing module mypy. I am trying to append ints and floats to an array, which I typed statically to be Real. But mypy says that they are incompatible types with Real. I though…

Search/Find functionality in QTableView

I have a QWidget and inside that, there is a QTableView. I need to have a find functionality on the first column of the table, so when I click on Ctrl+F, a find dialog will pop-up.class Widget(QWidget)…

How does searching with pip work?

Yes, Im dead serious with this question. How does searching with pip work?The documentation of the keyword search refers to a "pip search reference" at https://pip.pypa.io/en/stable/user_gui…

keras LSTM feeding input with the right shape

I am getting some data from a pandas dataframe with the following shapedf.head() >>> Value USD Drop 7 Up 7 Mean Change 7 Change Predict 0.06480 2.0 4.0 -0.000429 …

Problems with a binary one-hot (one-of-K) coding in python

Binary one-hot (also known as one-of-K) coding lies in making one binary column for each distinct value for a categorical variable. For example, if one has a color column (categorical variable) that ta…

How to hide the title bar in pygame?

I was wondering does anyone know how to hide the pygame task bar?I really need this for my pygame program!Thanks!

Deleting existing class variable yield AttributeError

I am manipulating the creation of classes via Pythons metaclasses. However, although a class has a attribute thanks to its parent, I can not delete it.class Meta(type):def __init__(cls, name, bases, dc…

Setting global font size in kivy

What is the preferred way, whether through python or the kivy language, to set the global font size (i.e. for Buttons and Labels) in kivy? What is a good way to dynamically change the global font size…

What is the difference between load name and load global in python bytecode?

load name takes its argument and pushes onto the stack the value of the name stored by store name at the position indicated by the argument . load global does something similar, but there appears to …

porting Python 2 program to Python 3, random line generator

I have a random line generator program written in Python2, but I need to port it to Python3. You give the program the option -n [number] and a file argument to tell it to randomly output [number] numbe…