This is a Polars extension that adds support for the H3 discrete global grid system, so you can index points and geometries to hexagons directly in Polars. All credits goes to the h3o for doing the heavy lifting.
-
π Blazing Fast: Built entirely in Rust, offering vectorized, multi-core H3 operations within Polars. Ideal for high-performance data processing.
-
π H3 Feature Parity: Comprehensive support for H3 functions, covering almost everything the standard H3 library provides, excluding geometric functions.
-
π Fully Tested: Thoroughly tested against the standard H3 library.
-
π Data Type Agnostic: Supports string and integer H3 indexes natively, eliminating format conversion hassles.
You can get started by installing it with pip (or uv):
pip install polars-h3
You can use the extension as a drop-in replacement for the standard H3 functions.
import polars_h3 as plh3
import polars as pl
>>> df = pl.DataFrame(
... {
... "lat": [37.7749],
... "long": [-122.4194],
... }
... ).with_columns(
... plh3.latlng_to_cell(
... "lat",
... "long",
... resolution=7,
... return_dtype=pl.Utf8
... ).alias("h3_cell"),
... )
>>> df
shape: (1, 3)
βββββββββββ¬ββββββββββββ¬ββββββββββββββββββ
β lat β long β h3_cell β
β --- β --- β --- β
β f64 β f64 β str β
βββββββββββͺββββββββββββͺββββββββββββββββββ‘
β 37.7749 β -122.4194 β 872830828ffffff β
βββββββββββ΄ββββββββββββ΄ββββββββββββββββββ
Check out the quickstart notebook for more examples.
π You can also find the advanced notebooks here.
This extension implements most of the H3 API. The full list of functions is below - you can find full docs here.
β οΈ Performance Note: When possible, prefer usingpl.UInt64
for H3 indices instead of thepl.Utf8
representation. String representations require casting operations which impact performance. Working directly with the native 64-bit integer format provides better computational efficiency.
We are unable to support the functions that work with geometries.
β = Supported π§ = Pending π = Not supported
Function | Description | Supported |
---|---|---|
latlng_to_cell |
Convert latitude/longitude coordinate to cell ID | β |
cell_to_lat |
Convert cell ID to latitude | β |
cell_to_lng |
Convert cell ID to longitude | β |
cell_to_latlng |
Convert cell ID to latitude/longitude | β |
get_resolution |
Get resolution number of cell ID | β |
str_to_int |
Convert pl.Utf8 cell ID to pl.UInt64 | β |
int_to_str |
Convert pl.UInt64 or pl.Int64 cell ID to pl.Utf8 | β |
is_valid_cell |
True if this is a valid cell ID | β |
is_res_class_iii |
True if the cell's resolution is class III | β |
is_pentagon |
True if the cell is a pentagon | β |
get_icosahedron_faces |
List of icosahedron face IDs the cell is on | β |
cell_to_parent |
Get coarser cell for a cell | β |
cell_to_children |
Get finer cells for a cell | β |
cell_to_center_child |
Provides the center child (finer) cell contained by cell at resolution childRes. | β |
cell_to_child_pos |
Position of the child cell within the ordered list of all children of its parent at the specified resolution | β |
child_pos_to_cell |
Child cell at a given position within the ordered list of children for a specified parent/resolution | β |
compact_cells |
Compacts a collection of H3 cells (all same resolution) by replacing child cells with their parent if all children exist | β |
uncompact_cells |
Uncompacts a set of H3 cells to the resolution res |
β |
grid_ring |
Produces the "hollow ring" of cells which are exactly grid distance k from the origin cell | β |
grid_disk |
Produces the "filled-in disk" of cells at most grid distance k from the origin cell | β |
grid_path_cells |
Find a grid path to connect two cells | β |
grid_distance |
Find the grid distance between two cells | β |
cell_to_local_ij |
Convert a cell ID to a local I,J coordinate space | β |
local_ij_to_cell |
Convert a local I,J coordinate to a cell ID | β |
cell_to_boundary |
Convert cell ID to its boundary lat/lng coordinates | β |
cell_to_vertex |
Get the vertex ID for a cell ID and vertex number | β |
cell_to_vertexes |
Get all vertex IDs for a cell ID (5 for pentagon, 6 for hex) | β |
vertex_to_latlng |
Convert a vertex ID to latitude/longitude coordinates | β |
is_valid_vertex |
True if passed a valid vertex ID | β |
is_valid_directed_edge |
True if passed a valid directed edge ID | β |
origin_to_directed_edges |
Get all directed edge IDs for a cell ID | β |
directed_edge_to_cells |
Convert a directed edge ID to origin/destination cell IDs | β |
get_directed_edge_origin |
Convert a directed edge ID to origin cell ID | β |
get_directed_edge_destination |
Convert a directed edge ID to destination cell ID | β |
cells_to_directed_edge |
Convert an origin/destination pair to directed edge ID | β |
are_neighbor_cells |
True if the two cell IDs share an edge | β |
average_hexagon_area |
Get average area of a hexagon cell at resolution | β |
cell_area |
Get the area of a cell ID | β |
average_hexagon_edge_length |
Average hexagon edge length at resolution | β |
edge_length |
Get the length of a directed edge ID (currently raises NotImplementedError ) |
π§ |
get_num_cells |
Get the number of cells at a resolution | β |
get_pentagons |
Get all pentagons at a resolution (currently raises NotImplementedError ) |
π§ |
great_circle_distance |
Compute the great circle distance between two points (haversine) | β |
cells_to_multi_polygon_wkt |
Convert a set of cells to multipolygon WKT | π |
polygon_wkt_to_cells |
Convert polygon WKT to a set of cells | π |
directed_edge_to_boundary_wkt |
Convert directed edge ID to linestring WKT | π |
The library also comes with helper functions to plot hexes on a Folium map.
import polars_h3 as plh3
import polars as pl
hex_map = plh3.graphing.plot_hex_outlines(df, "h3_cell")
display(hex_map)
# or if you have a metric to plot
hex_map = plh3.graphing.plot_hex_fills(df, "h3_cell", "metric_col")
display(hex_map)
It's recommended to use uv to manage the extension dependencies. If you modify rust code, you will need to run uv run maturin develop --uv
to see changes. If you're looking to benchmark the performance of the extension, build the release version with maturin develop --release --uv
and then run uv run -m benchmarks.engine
(assuming you have the benchmark dependencies installed). Benchmarking with the development version will lead to misleading results.