Learn R Programming

hexify

Equal-Area Hexagonal Grids for Global Spatial Analysis

The hexify package provides fast, accurate assignment of geographic coordinates to equal-area hexagonal grid cells using the ISEA (Icosahedral Snyder Equal Area) discrete global grid system. Whether you're aggregating species occurrences, analyzing point patterns, or preparing data for spatial modeling, hexify ensures every cell has identical area from the equator to the poles.

Quick Start

library(hexify)

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

# Option 1: Create grid first, then assign points
grid <- hex_grid(area_km2 = 10000)
result <- hexify(cities, lon = "lon", lat = "lat", grid = grid)

# Option 2: Set grid parameters directly in hexify()
result <- hexify(cities, lon = "lon", lat = "lat", area_km2 = 10000)

# Visualize
plot(result)

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 ISEA hexagonal grids with multiple apertures (3, 4, 7, or mixed 4/3), the same system used by major biodiversity databases and spatial frameworks. This package provides:

  • Consistent cell areas regardless of latitude
  • Deterministic cell assignment for reproducible workflows
  • Fast C++ implementation handling millions of points
  • Direct compatibility with dggridR cell IDs

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

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.3.10

License

MIT + file LICENSE

Maintainer

Gilles Colling

Last Published

February 4th, 2026

Functions in hexify (0.3.10)

grid_global

Generate a global hexagon grid
hex_corners_to_sf

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

Generate a rectangular grid of hexagons
grid_info

Get Grid Specification
grid_clip

Clip hexagon grid to polygon boundary
hex_grid

Create a Hexagonal Grid Specification
hexify-conversions

Coordinate Conversions
globe_centers

Globe center presets
hexify-stats

Grid Statistics
hexify_cell_id_to_quad_ij

Get cell info from cell ID
hexify_build_icosa

Initialize icosahedron geometry
hexify-package

hexify
hexify-grid

Core Grid Construction
hexify_cell_to_index

Convert cell coordinates to index string
dggrid_is_compatible

Validate 'dggridR' grid compatibility with hexify
dgverify

Verify grid object
hexify_compare_indices

Compare two indices
hexify_cell_to_icosa_tri

Convert Cell ID to Icosa Triangle coordinates
hexify_cell_to_sf

Convert cell IDs to sf polygons
hexify_compare_resolutions

Compare grid resolutions
hexify_cell_to_plane

Convert Cell ID to PLANE coordinates
hexify_default_index_type

Get default index type for aperture
hexify_cell_to_lonlat

Convert cell ID to longitude/latitude
hexify_cell_to_quad_xy

Convert Cell ID to Quad XY coordinates
hexify_cell_to_quad_ij

Convert Cell ID to Quad IJ coordinates
hexify_get_children

Get children indices
hexify_get_precision

Get current precision settings
hexify_get_parent

Get parent index
hexify_grid_cell_to_lonlat

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

Generate a global grid of hexagon polygons
cell_to_lonlat

Convert cell ID to longitude/latitude
cell_to_sf

Convert cell IDs to sf polygons
hexify_forward_to_face

Forward projection to specific face
get_children

Get children cells
get_parent

Get parent cell
hexify_assign

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

Convert area to effective resolution
hexify_icosa_tri_to_quad_ij

Convert Icosa Triangle to Quad IJ coordinates
hexify_grid_to_cell

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

Convert longitude/latitude to hexagonal cell hierarchical index
hexify_icosa_tri_to_quad_xy

Convert Icosa Triangle to Quad XY coordinates
hexify_face_centers

Get icosahedron face centers
hexify_world

Simplified World Map
hexify_get_resolution

Get index resolution
hexify_h_index_to_lonlat

Convert hierarchical index strings to longitude/latitude centers
hexify_lonlat_to_cell

Convert longitude/latitude to cell ID
hexify_set_verbose

Set verbose mode for inverse projection
hexify_grid

Create a hexagonal grid specification
hexify_heatmap

Create a ggplot2 visualization of hexagonal grid cells
hexify_projection_stats

Get inverse projection statistics
hexify

Assign hexagonal DGGS cell IDs to geographic points
hexify_forward

Forward Snyder projection
hexify_grid_to_HexGridInfo

Convert legacy hexify_grid to HexGridInfo
hexify_grid_rect

Generate a rectangular grid of hexagon polygons
hexify_quad_ij_to_cell

Convert Quad IJ coordinates to cell ID
hexify_index_to_lonlat

Convert index string to longitude/latitude
hexify_eff_res_to_area

Convert effective resolution to area
hexify_index_to_cell

Convert index string to cell coordinates
hexify_icosa_tri_to_plane

Convert Icosa Triangle coordinates to PLANE coordinates
plot_world

Quick world map plot
hexify_which_face

Determine which face contains a point
plot_grid

Plot hexagonal grid clipped to a polygon boundary
hexify_inverse

Inverse Snyder projection
n_cells

Get Number of Cells
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_eff_res_to_resolution

Convert effective resolution to index resolution
hexify_quad_ij_to_icosa_tri

Convert Quad IJ to Icosa Triangle coordinates
hexify_lonlat_to_quad_ij

Convert longitude/latitude to Quad IJ coordinates
plot,HexData,missing-method

Plot HexData objects
hexify_lonlat_to_plane

Convert longitude/latitude to PLANE coordinates
new_hex_data

Create a HexData Object (Internal)
hexify_z7_canonical

Get canonical form of Z7 index
hexify_lonlat_to_index

Convert longitude/latitude to index string
hexify_roundtrip_test

Round-trip accuracy test
hexify_set_precision

Set inverse projection precision
index_to_cell_internal

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

Check if index type is valid for aperture
lonlat_to_cell

Convert longitude/latitude to cell ID
is_hex_grid

Check if object is HexGridInfo
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)
is_hex_data

Check if object is HexData
plot_globe

Plot hexagonized globe
HexData-class

HexData Class
calculate_resolution_for_area

Calculate resolution for target area
as_sf

Convert HexData to sf Object
HexGridInfo-class

HexGridInfo Class
as_dggrid

Convert hexify grid to 'dggridR'-compatible grid object
as_tibble.HexData

Convert HexData to tibble
dgearthstat

Get grid statistics for Earth coverage
cells

Get Cell IDs
HexGridInfo_to_hexify_grid

Convert HexGridInfo to legacy hexify_grid
dg_closest_res_to_area

Find closest resolution for target cell area
HexGridInfo-methods

HexGridInfo S4 Methods
cell_to_index

Convert cell ID to hierarchical index string
HexData-methods

HexData S4 Methods
extract_grid

Extract grid from various objects
from_dggrid

Convert 'dggridR' grid object to hexify_grid
dggrid_43h_sequence

Create DGGRID 43H aperture sequence