H3 Hexagonal Indexing — Core Concepts
H3 is Uber’s open-source hierarchical spatial indexing system that partitions Earth’s surface into hexagonal cells at 16 resolution levels. The Python h3 library exposes the full H3 API for geocoding, neighbor traversal, aggregation, and polygon operations.
Coordinate to cell
import h3
lat, lng = 40.748, -73.985
cell = h3.latlng_to_cell(lat, lng, res=9)
print(cell) # '892a100d2c3ffff'
The cell index is a 64-bit integer encoded as a hex string. It uniquely identifies one hexagon at the given resolution.
Resolution levels
| Resolution | Avg edge length | Avg area | Typical use |
|---|---|---|---|
| 0 | 1,108 km | 4.25M km² | Continental |
| 3 | 59 km | 12,393 km² | Regional |
| 5 | 8 km | 253 km² | Metro area |
| 7 | 1.2 km | 5.2 km² | Neighborhood |
| 9 | 174 m | 105,332 m² | City block |
| 11 | 25 m | 2,149 m² | Building |
| 13 | 3.6 m | 44 m² | Parking space |
| 15 | 0.5 m | 0.9 m² | Sub-meter |
Choose the resolution that matches your analysis granularity. Too fine wastes computation; too coarse loses detail.
Cell properties
# Center point of a cell
lat, lng = h3.cell_to_latlng(cell)
# Boundary vertices (for drawing the hexagon)
boundary = h3.cell_to_boundary(cell) # list of (lat, lng) tuples
# Area in square meters
area = h3.cell_area(cell, unit="m^2")
# Resolution
res = h3.get_resolution(cell)
Neighbor traversal
# Immediate neighbors (k-ring with k=1)
neighbors = h3.grid_disk(cell, k=1) # 7 cells (center + 6 neighbors)
# Ring only (excludes center)
ring = h3.grid_ring(cell, k=1) # 6 cells
# Larger neighborhood
area = h3.grid_disk(cell, k=3) # 37 cells
K-ring operations are constant-time — they use index arithmetic, not spatial queries.
Hierarchical operations
# Parent cell (coarser resolution)
parent = h3.cell_to_parent(cell, res=7)
# Children cells (finer resolution)
children = h3.cell_to_children(cell, res=11)
print(len(children)) # ~49 children (7 per level, 2 levels)
This hierarchy enables drill-down analysis: aggregate at resolution 7 for an overview, then expand to resolution 9 for detail in a specific area.
Aggregating data
The most common pattern: group location data by H3 cell and count or sum.
import pandas as pd
df = pd.read_csv("events.csv")
df["h3_cell"] = df.apply(
lambda row: h3.latlng_to_cell(row["lat"], row["lng"], res=9),
axis=1,
)
cell_counts = df.groupby("h3_cell").size().reset_index(name="count")
For visualization, convert cells to polygons:
import geopandas as gpd
from shapely.geometry import Polygon
cell_counts["geometry"] = cell_counts["h3_cell"].apply(
lambda c: Polygon(h3.cell_to_boundary(c))
)
gdf = gpd.GeoDataFrame(cell_counts, geometry="geometry", crs="EPSG:4326")
Polyfill: covering a polygon with hexagons
# GeoJSON polygon defining an area of interest
polygon = {
"type": "Polygon",
"coordinates": [[
[-73.99, 40.75], [-73.95, 40.75],
[-73.95, 40.70], [-73.99, 40.70], [-73.99, 40.75]
]]
}
cells = h3.polygon_to_cells(
h3.LatLngPoly(polygon["coordinates"][0]),
res=9,
)
print(len(cells)) # cells covering the polygon
Common misconception
H3 cells are not perfect hexagons everywhere. Due to the icosahedral projection, 12 cells at each resolution are pentagons instead of hexagons. These pentagons sit at the vertices of the underlying icosahedron and rarely appear in practical analysis (they fall in remote ocean areas), but code should handle them gracefully.
The one thing to remember: H3 gives every spot on Earth a hexagonal address at any zoom level — group by that address to instantly aggregate, compare, and visualize spatial data without defining custom boundaries.
See Also
- Python Adaptive Learning Systems How Python builds learning apps that adjust to each student like a personal tutor who knows exactly what you need next.
- Python Airflow Learn Airflow as a timetable manager that makes sure data tasks run in the right order every day.
- Python Altair Learn Altair through the idea of drawing charts by describing rules, not by hand-placing every visual element.
- Python Automated Grading How Python grades homework and exams automatically, from simple answer keys to understanding written essays.
- Python Batch Vs Stream Processing Batch processing is like doing laundry once a week; stream processing is like a self-cleaning shirt that cleans itself constantly.