Working with H3
H3 is a hexagonal global grid system. It's a good fit when you need to:
- Build heatmaps of events (populations, counts, etc.)
- Compare datasets across resolutions and scale
- Work with sparse datasets, like point or location data
You can try all of the basics of H3 on this Canvas →
A typical H3 workflow has four stages: convert your source data into hexagons, pick a resolution that fits your data and use case, aggregate to make the data useful at different zoom levels, and join it with other H3 datasets for analysis.
1. Convert your data to H3
How you convert depends on your data's type and size:
| Data | Size | Approach | API |
|---|---|---|---|
| Point / vector (CSV, GeoJSON, Parquet) | Small (< 100MB) | On the fly, per-request | h3_latlng_to_cell() via DuckDB |
| Vector polygons | Small or large | On the fly, per viewport (Tile UDF mode) | common.gdf_to_hex(), see Dynamic Tile to H3 |
| Raster (GeoTIFF, COG, etc.) | Large (> 100MB) | Pre-computed ingestion | fused.h3.run_ingest_raster_to_h3() |
| Vector (points/polygons) | Large (> 100k features) | Pre-computed, parallelized with .map() | see Vector to H3 |
Small datasets can be hexagonified on the fly inside a single UDF. Large rasters and vector datasets are better pre-computed once with run_ingest_raster_to_h3() or .map(), then read back with read_h3_dataset() — this avoids re-processing the same data on every request.
If your dataset doesn't fit the patterns above (hundreds of GB, tens of thousands of files, or a custom ingestion shape), reach out to info@fused.io — we can help you scale the ingestion or point you to the right execution engine.
Full examples and code for each path are in Converting to H3.
2. Pick a resolution
The resolution (res) controls hex size, and it drives everything downstream — conversion fidelity, how much data you store, and the granularity available for aggregation and joins. By default, resolution is inferred from the input (e.g. raster pixel size), but you can set it explicitly.
| Resolution | Avg edge length | Typical use case |
|---|---|---|
| 3 | 59.81 km | Regional |
| 7 | 1.22 km | Neighborhood |
| 9 | 174.38 m | Block |
| 12 | 10.8 m | Building |
See the Resolution Guide for the full table and how Fused infers resolution from raster pixel size.
3. Aggregate
Resolution and aggregation go hand in hand: once data is in H3 at a base resolution, you aggregate it up to coarser (parent) resolutions to make it fast to render and analyze at different zoom levels — ingestion already pre-computes these as overview files, so zooming out doesn't mean re-scanning the base data. Aggregation is also the precursor to joining: two datasets need to share a resolution before they can be joined cell-by-cell.
How you aggregate depends on the data type:
- Numerical (temperature, elevation, population): sum, mean, max, min, or stddev per cell.
- Categorical (land use, crop type): count occurrences, or take the mode, per cell.
You can also derive new layers from aggregated data — e.g. computing slope from an elevation layer using neighboring cells (h3_grid_ring).
See Aggregations for the full examples.
4. Join datasets
Once two H3 datasets share the same hex column and resolution, merging them is a standard SQL join (via DuckDB) on hex — no spatial join needed. This is the easiest way to combine datasets that would otherwise be hard to merge directly, such as:
- Datasets in different spatial projections
- Sparse datasets like location data
- Datasets at different native resolutions or of different types (raster + vector)
See Joining for a worked example merging an elevation layer with a crop-type layer.
5. Visualize
Once your H3 data is converted, aggregated, and (optionally) joined, you have two options to render it as hexagons:
- Workbench Map Viewer: style it directly as a vector
H3HexagonLayer, with or without tiles. - Canvas: combine UDFs into an interactive visualization.
For more detail, see Visualization.
Reference
fused.h3— Python SDK reference for H3 ingestion functions- H3 Analytics section — full walkthroughs with runnable code for every step above
- Need help with a large or unusual dataset? Contact info@fused.io