Learn R Programming

hexify

Hexagonal Grids for Global Spatial Analysis — ISEA + H3

The hexify package provides fast, accurate assignment of geographic coordinates to hexagonal grid cells. It supports two grid systems: ISEA (Icosahedral Snyder Equal Area) for guaranteed equal-area cells, and H3 (Uber's hierarchical hex system) for compatibility with industry-standard workflows like FCC broadband mapping. Whether you're aggregating species occurrences, analyzing point patterns, or preparing data for spatial modeling, hexify gives you one consistent interface for both systems.

Quick Start

library(hexify)

cities <- data.frame(
  name = c("Vienna", "Paris", "Madrid"),
  lon = c(16.37, 2.35, -3.70),
  lat = c(48.21, 48.86, 40.42)
)

# ISEA equal-area grid (default)
grid <- hex_grid(area_km2 = 10000)
result <- hexify(cities, lon = "lon", lat = "lat", grid = grid)
plot(result)

# H3 grid (Uber's system)
h3_grid <- hex_grid(resolution = 4, type = "h3")
result_h3 <- hexify(cities, lon = "lon", lat = "lat", grid = h3_grid)
plot(result_h3)

Statement of Need

Spatial binning is fundamental to ecological modeling, epidemiology, and geographic analysis. Standard approaches using rectangular lat-lon grids introduce severe area distortions: a 1° cell at the equator covers ~12,300 km², while the same cell near the poles covers a fraction of that area. This violates the equal-sampling assumption underlying most spatial statistics.

Discrete Global Grid Systems (DGGS) solve this by partitioning Earth's surface into cells of uniform area. hexify implements two hex grid systems:

  • ISEA — True equal-area hexagonal grids with apertures 3, 4, 7, or mixed 4/3. Fast C++ implementation. Compatible with dggridR cell IDs.
  • H3 — Uber's hierarchical hexagonal system (resolutions 0–15). Industry standard used by the FCC, Foursquare, and others. Powered by the h3o package.

Both systems share the same interface: hexify(), cell_to_sf(), grid_rect(), get_parent(), get_children(), and all other functions work with either grid type.

These features make hexify suitable for:

  • Species distribution modeling and biodiversity assessments
  • Epidemiological surveillance and disease mapping
  • Environmental monitoring and remote sensing aggregation
  • Any analysis requiring unbiased spatial binning

Features

Core Workflow

  • hex_grid(): Define a grid by target cell area (km²) or resolution level
  • hexify(): Assign points to grid cells (data.frame or sf input)
  • plot() / hexify_heatmap(): Visualize results with base R or ggplot2

Grid Generation

  • grid_rect(): Generate cell polygons for a bounding box
  • grid_global(): Generate a complete global grid (all cells)
  • grid_clip(): Clip grid to a polygon boundary (country, region, etc.)

Cell Operations

  • cell_to_sf(): Convert cell IDs to sf polygon geometries
  • cell_to_lonlat(): Get cell center coordinates
  • get_parent() / get_children(): Navigate grid hierarchy

Interoperability

  • as_dggrid() / from_dggrid(): Convert to/from dggridR format
  • as_sf(): Export HexData to sf object
  • as.data.frame(): Extract data with cell assignments
  • H3 support: hex_grid(resolution = 8, type = "h3") — requires h3o package

Installation

# Install from CRAN
install.packages("hexify")

# Or install development version from GitHub
# install.packages("pak")
pak::pak("gcol33/hexify")

Usage Examples

Basic Point Assignment

library(hexify)

# Define grid: ~10,000 km² cells
grid <- hex_grid(area_km2 = 10000)
grid
#> HexGridInfo: aperture=3, resolution=5, area=12364.17 km²

# Assign coordinates to cells
coords <- data.frame(
  lon = c(-122.4, 2.35, 139.7),
  lat = c(37.8, 48.9, 35.7)
)
result <- hexify(coords, lon = "lon", lat = "lat", grid = grid)

# Access cell IDs
result@cell_id

Working with sf Objects

library(sf)

# Any CRS works - hexify transforms automatically
points_sf <- st_as_sf(coords, coords = c("lon", "lat"), crs = 4326)
result <- hexify(points_sf, area_km2 = 10000)

# Export back to sf
result_sf <- as_sf(result)

Generating Grid Polygons

# Grid for Europe
grid <- hex_grid(area_km2 = 50000)
europe_hexes <- grid_rect(c(-10, 35, 40, 70), grid)
plot(europe_hexes["cell_id"])

# Clip to a country boundary
library(rnaturalearth)
france <- ne_countries(country = "France", returnclass = "sf")
france_grid <- grid_clip(france, grid)

Aggregating Point Data

# Species occurrence data
occurrences <- data.frame(
  species = sample(c("Sp A", "Sp B", "Sp C"), 1000, replace = TRUE),
  lon = runif(1000, -10, 30),
  lat = runif(1000, 35, 60)
)

# Assign to grid
grid <- hex_grid(area_km2 = 20000)
occ_hex <- hexify(occurrences, lon = "lon", lat = "lat", grid = grid)

# Count per cell
occ_df <- as.data.frame(occ_hex)
occ_df$cell_id <- occ_hex@cell_id

cell_counts <- aggregate(species ~ cell_id, data = occ_df, FUN = length)
names(cell_counts)[2] <- "n_records"

# Richness per cell
richness <- aggregate(species ~ cell_id, data = occ_df,
                      FUN = function(x) length(unique(x)))
names(richness)[2] <- "n_species"

Visualization

# Quick plot
plot(result)

# Heatmap with basemap
hexify_heatmap(occ_hex, value = "n_records", basemap = TRUE)

# Custom ggplot
library(ggplot2)
cell_polys <- cell_to_sf(cell_counts$cell_id, grid)
cell_polys <- merge(cell_polys, cell_counts, by = "cell_id")

ggplot(cell_polys) +
  geom_sf(aes(fill = n_records), color = "white", linewidth = 0.2) +
  scale_fill_viridis_c() +
  theme_minimal()

Documentation

Support

"Software is like sex: it's better when it's free." — Linus Torvalds

I'm a PhD student who builds R packages in my free time because I believe good tools should be free and open. I started these projects for my own work and figured others might find them useful too.

If this package saved you some time, buying me a coffee is a nice way to say thanks. It helps with my coffee addiction.

Citation

@software{hexify,
  author = {Colling, Gilles},
  title = {hexify: Equal-Area Hexagonal Grids for Spatial Analysis},
  year = {2025},
  url = {https://CRAN.R-project.org/package=hexify},
  doi = {10.32614/CRAN.package.hexify}
}

License

MIT (see LICENSE.md)

Copy Link

Version

Install

install.packages('hexify')

Version

0.6.5

License

MIT + file LICENSE

Maintainer

Gilles Colling

Last Published

February 28th, 2026

Functions in hexify (0.6.5)

dggrid_is_compatible

Validate 'dggridR' grid compatibility with hexify
dggrid_43h_sequence

Create DGGRID 43H aperture sequence
dgverify

Verify grid object
grid_rect

Generate a rectangular grid of hexagons
grid_info

Get Grid Specification
get_parent

Get parent cell
globe_centers

Globe center presets
grid_global

Generate a global hexagon grid
cells

Get Cell IDs
grid_clip

Clip hexagon grid to polygon boundary
hexify-stats

Grid Statistics
hex_corners_to_sf

Build an sf POLYGON from six (lon, lat) corner pairs
h3_crosswalk

Crosswalk Between ISEA and H3 Cell IDs
get_children

Get children cells
from_dggrid

Convert 'dggridR' grid object to hexify_grid
hex_grid

Create a Hexagonal Grid Specification
hexify-package

hexify
hexify-conversions

Coordinate Conversions
hexify-grid

Core Grid Construction
hexify

Assign hexagonal DGGS cell IDs to geographic points
hexify_compare_resolutions

Compare grid resolutions
hexify_default_index_type

Get default index type for aperture
hexify_build_icosa

Initialize icosahedron geometry
hexify_area_to_eff_res

Convert area to effective resolution
extract_grid

Extract grid from various objects
hexify_cell_id_to_quad_ij

Get cell info from cell ID
hexify_assign

Assign hex cells ('ISEA3H', aperture 3) for lon/lat
hexify_cell_to_sf

Convert cell IDs to sf polygons
hexify_eff_res_to_area

Convert effective resolution to area
hexify_get_parent

Get parent index
hexify_forward_to_face

Forward projection to specific face
hexify_cell_to_quad_xy

Convert Cell ID to Quad XY coordinates
hexify_grid_cell_to_lonlat

Convert cell ID to longitude/latitude using a grid object
hexify_cell_to_lonlat

Convert cell ID to longitude/latitude
hexify_grid_global

Generate a global grid of hexagon polygons
hexify_cell_to_quad_ij

Convert Cell ID to Quad IJ coordinates
hexify_cell_to_plane

Convert Cell ID to PLANE coordinates
hexify_face_centers

Get icosahedron face centers
hexify_forward

Forward Snyder projection
hexify_icosa_tri_to_quad_xy

Convert Icosa Triangle to Quad XY coordinates
hexify_compare_indices

Compare two indices
hexify_icosa_tri_to_quad_ij

Convert Icosa Triangle to Quad IJ coordinates
hexify_heatmap

Create a ggplot2 visualization of hexagonal grid cells
hexify_h_index_to_lonlat

Convert hierarchical index strings to longitude/latitude centers
hexify_grid_to_cell

Convert longitude/latitude to cell ID using a grid object
hexify_eff_res_to_resolution

Convert effective resolution to index resolution
hexify_get_children

Get children indices
hexify_inverse

Inverse Snyder projection
hexify_lonlat_to_cell

Convert longitude/latitude to cell ID
hexify_lonlat_to_h_index

Convert longitude/latitude to hexagonal cell hierarchical index
hexify_icosa_tri_to_plane

Convert Icosa Triangle coordinates to PLANE coordinates
hexify_which_face

Determine which face contains a point
hexify_projection_stats

Get inverse projection statistics
hexify_set_verbose

Set verbose mode for inverse projection
hexify_lonlat_to_quad_ij

Convert longitude/latitude to Quad IJ coordinates
hexify_resolution_to_eff_res

Convert index resolution to effective resolution
hexify_quad_xy_to_icosa_tri

Convert Quad XY to Icosa Triangle coordinates
hexify_is_valid_index_type

Check if index type is valid for aperture
hexify_get_precision

Get current precision settings
hexify_grid_rect

Generate a rectangular grid of hexagon polygons
hexify_grid_to_HexGridInfo

Convert legacy hexify_grid to HexGridInfo
hexify_index_to_cell

Convert index string to cell coordinates
hexify_roundtrip_test

Round-trip accuracy test
hexify_set_precision

Set inverse projection precision
is_hex_grid

Check if object is HexGridInfo
hexify_world

Simplified World Map
hexify_z7_canonical

Get canonical form of Z7 index
hexify_index_to_lonlat

Convert index string to longitude/latitude
lonlat_to_cell

Convert longitude/latitude to cell ID
hexify_quad_ij_to_cell

Convert Quad IJ coordinates to cell ID
hexify_grid

Create a hexagonal grid specification
hexify_cell_to_icosa_tri

Convert Cell ID to Icosa Triangle coordinates
hexify_get_resolution

Get index resolution
hexify_cell_to_index

Convert cell coordinates to index string
n_cells

Get Number of Cells
is_hex_data

Check if object is HexData
new_hex_data

Create a HexData Object (Internal)
hexify_quad_ij_to_icosa_tri

Convert Quad IJ to Icosa Triangle coordinates
index_to_cell_internal

Decode a cell index to face, i, j, and resolution
plot_grid

Plot hexagonal grid clipped to a polygon boundary
plot_globe

Plot hexagonized globe
plot,HexData,missing-method

Plot HexData objects
hexify_lonlat_to_plane

Convert longitude/latitude to PLANE coordinates
hexify_lonlat_to_index

Convert longitude/latitude to index string
hexify_quad_xy_to_cell

Convert Quad XY coordinates to Cell ID
hexify_quad_ij_to_xy

Convert Quad IJ to Quad XY (continuous coordinates)
plot_world

Quick world map plot
as_sf

Convert HexData to sf Object
HexGridInfo_to_hexify_grid

Convert HexGridInfo to legacy hexify_grid
cell_area

Compute per-cell area in km²
cell_to_sf

Convert cell IDs to sf polygons
as_tibble.HexData

Convert HexData to tibble
as_dggrid

Convert hexify grid to 'dggridR'-compatible grid object
HexGridInfo-class

HexGridInfo Class
HexData-class

HexData Class
calculate_resolution_for_area

Calculate resolution for target area
dgearthstat

Get grid statistics for Earth coverage
dg_closest_res_to_area

Find closest resolution for target cell area
HexData-methods

HexData S4 Methods
cell_to_index

Convert cell ID to hierarchical index string
HexGridInfo-methods

HexGridInfo S4 Methods
cell_to_lonlat

Convert cell ID to longitude/latitude