|
| 1 | +--- |
| 2 | +title: "`h3o` is now on CRAN‼️" |
| 3 | +description: | |
| 4 | + R users now have access to a pure Rust implementation of Uber's H3, a |
| 5 | + hexagonal geospatial grid and indexing system. |
| 6 | +author: |
| 7 | + - name: Blake Vernon |
| 8 | + - name: Josiah Parry |
| 9 | +date: "2025/09/09" |
| 10 | +image: thumbnail.png |
| 11 | +image-alt: "The letters h3o on a hexagonal sticker." |
| 12 | +categories: [Release] |
| 13 | +--- |
| 14 | + |
| 15 | +The extendr-powered R package `h3o` provides access to [a pure Rust implementation](https://github.com/HydroniumLabs/h3o) |
| 16 | +of [Uber's H3 Geospatial Indexing System](https://github.com/uber/h3). |
| 17 | +Originally developed by Josiah Parry, the R package has also become an official |
| 18 | +product of extendr, which means community support 🤝 and maintenance 🏗️ into |
| 19 | +the foreseeable future. |
| 20 | + |
| 21 | +## `h3o` at a glance 👀 |
| 22 | + |
| 23 | +The package provides functionality to interact with H3's grid as vectors, which |
| 24 | +can be converted to and from `sf` geometries. |
| 25 | + |
| 26 | +```{r} |
| 27 | +#| label: example |
| 28 | +#| warning: false |
| 29 | +#| message: false |
| 30 | +library(h3o) |
| 31 | +library(dplyr) |
| 32 | +library(sf) |
| 33 | +library(tibble) |
| 34 | +
|
| 35 | +xy <- data.frame( |
| 36 | + x = runif(100, -5, 10), |
| 37 | + y = runif(100, 40, 50) |
| 38 | +) |
| 39 | +
|
| 40 | +pnts <- st_as_sf( |
| 41 | + xy, |
| 42 | + coords = c("x", "y"), |
| 43 | + crs = 4326 |
| 44 | +) |
| 45 | +
|
| 46 | +pnts |> mutate(h3 = h3_from_points(geometry, 5)) |
| 47 | +``` |
| 48 | + |
| 49 | +You can use the `st_as_sfc()` method to convert H3 hexagons to sf `POLYGON`s. |
| 50 | + |
| 51 | +```{r} |
| 52 | +# replace geometry |
| 53 | +h3_cells <- pnts |> |
| 54 | + mutate( |
| 55 | + h3 = h3_from_points(geometry, 4), |
| 56 | + geometry = st_as_sfc(h3) |
| 57 | + ) |
| 58 | +
|
| 59 | +# plot the hexagons |
| 60 | +plot(st_geometry(h3_cells)) |
| 61 | +``` |
| 62 | + |
| 63 | +H3 cell centroids can be returned using `h3_to_points()`. If `sf` is avilable, |
| 64 | +the results will be returned as an `sfc` (sf column) object. Otherwise it will |
| 65 | +return a list of `sfg` (sf geometries). |
| 66 | + |
| 67 | +```{r} |
| 68 | +# fetch h3 column |
| 69 | +h3s <- h3_cells[["h3"]] |
| 70 | +
|
| 71 | +# get there centers |
| 72 | +h3_centers <- h3_to_points(h3s) |
| 73 | +
|
| 74 | +# plot the hexagons with the centers |
| 75 | +plot(st_geometry(h3_cells)) |
| 76 | +plot(h3_centers, pch = 16, add = TRUE, col = "black") |
| 77 | +``` |
| 78 | + |
| 79 | +## H3 at light speed ⚡ |
| 80 | + |
| 81 | +Because it builds on a pure Rust implementation, `h3o` is also very very fast. |
| 82 | +Here are some benchmarks, which also serve to showcase `h3o` tools. |
| 83 | + |
| 84 | +### Creating polygons |
| 85 | + |
| 86 | +```{r} |
| 87 | +h3_strs <- as.character(h3s) |
| 88 | +bench::mark( |
| 89 | + h3o = st_as_sfc(h3s), |
| 90 | + h3jsr = h3jsr::cell_to_polygon(h3_strs), |
| 91 | + relative = TRUE |
| 92 | +) |
| 93 | +``` |
| 94 | + |
| 95 | +### Converting polygons to H3 cells: |
| 96 | + |
| 97 | +```{r} |
| 98 | +nc <- st_read(system.file("gpkg/nc.gpkg", package = "sf"), quiet = TRUE) |> |
| 99 | + st_transform(4326) |> |
| 100 | + st_geometry() |
| 101 | +
|
| 102 | +bench::mark( |
| 103 | + h3o = sfc_to_cells(nc, 5, "centroid"), |
| 104 | + h3jsr = h3jsr::polygon_to_cells(nc, 5), |
| 105 | + check = FALSE, |
| 106 | + relative = TRUE |
| 107 | +) |
| 108 | +``` |
| 109 | + |
| 110 | +### Converting points to cells |
| 111 | + |
| 112 | +```{r} |
| 113 | +bench::mark( |
| 114 | + h3o = h3_from_points(pnts$geometry, 3), |
| 115 | + h3jsr = h3jsr::point_to_cell(pnts$geometry, 3), |
| 116 | + check = FALSE, |
| 117 | + relative = TRUE |
| 118 | +) |
| 119 | +``` |
| 120 | + |
| 121 | +### Retrieve edges |
| 122 | + |
| 123 | +```{r} |
| 124 | +bench::mark( |
| 125 | + h3o = h3_edges(h3s), |
| 126 | + h3jsr = h3jsr::get_udedges(h3_strs), |
| 127 | + check = FALSE, |
| 128 | + relative = TRUE |
| 129 | +) |
| 130 | +``` |
| 131 | + |
| 132 | +### Get origins and destinations from edges. |
| 133 | + |
| 134 | +```{r} |
| 135 | +# get edges for a single location |
| 136 | +eds <- h3_edges(h3s[1])[[1]] |
| 137 | +# strings for h3jsr |
| 138 | +eds_str <- as.character(eds) |
| 139 | +
|
| 140 | +bench::mark( |
| 141 | + h3o = h3_edge_cells(eds), |
| 142 | + h3jsr = h3jsr::get_udends(eds_str), |
| 143 | + check = FALSE, |
| 144 | + relative = TRUE |
| 145 | +) |
| 146 | +``` |
| 147 | + |
| 148 | +## Installation 📦 |
| 149 | + |
| 150 | +You can install the release version of `h3o` from CRAN with: |
| 151 | + |
| 152 | +``` r |
| 153 | +install.packages("h3o") |
| 154 | +``` |
| 155 | + |
| 156 | +Or you can install the development version from [GitHub](https://github.com/) |
| 157 | +with: |
| 158 | + |
| 159 | +``` r |
| 160 | +# install.packages("pak") |
| 161 | +pak::pak("extendr/h3o") |
| 162 | +``` |
| 163 | + |
| 164 | +## Learn more 🧑🎓 |
| 165 | + |
| 166 | +See the package documentation for more details: <http://extendr.rs/h3o/>. |
| 167 | + |
| 168 | +If you encounter a bug or would like to request new features, head over to the |
| 169 | +GitHub repository: <https://github.com/extendr/h3o>. |
0 commit comments