Skip to content

Filimoa/polars-h3

Repository files navigation

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.

Highlights

  • πŸš€ 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.

Get started

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.

Implemented functions

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 using pl.UInt64 for H3 indices instead of the pl.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.

Full list of functions

βœ… = 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 πŸ›‘

Plotting

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)

CleanShot 2024-12-08 at 00 26 22

Development

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.