Skip to content

Commit 58b4032

Browse files
authored
Merge pull request #61 from extendr/blog-post-h3o
blog post for h3o
2 parents 779044b + 8c3ca33 commit 58b4032

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"hash": "6119954e7cd9d2742a652929e32451c6",
3+
"result": {
4+
"engine": "knitr",
5+
"markdown": "---\ntitle: \"`h3o` is now on CRAN‼️\"\ndescription: |\n R users now have access to a pure Rust implementation of Uber's H3, a \n hexagonal geospatial grid and indexing system.\nauthor: Blake Vernon\ndate: \"2025/09/09\"\nimage: thumbnail.png\nimage-alt: \"The letters h3o on a hexagonal sticker.\"\ncategories: [Release]\n---\n\nThe extendr-powered R package `h3o` provides access to [a pure Rust implementation](https://github.com/HydroniumLabs/h3o) \nof [Uber's H3 Geospatial Indexing System](https://github.com/uber/h3). \nOriginally developed by Josiah Parry, the R package has also become an official \nproduct of extendr, which means community support 🤝 and maintenance 🏗️ into \nthe foreseeable future.\n\n## `h3o` at a glance 👀\n\nThe package provides functionality to interact with H3's grid as vectors, which \ncan be converted to and from `sf` geometries. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(h3o)\nlibrary(dplyr)\nlibrary(sf)\nlibrary(tibble)\n\nxy <- data.frame(\n x = runif(100, -5, 10),\n y = runif(100, 40, 50)\n)\n\npnts <- st_as_sf(\n xy,\n coords = c(\"x\", \"y\"),\n crs = 4326\n)\n\npnts |> mutate(h3 = h3_from_points(geometry, 5))\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\nSimple feature collection with 100 features and 1 field\nGeometry type: POINT\nDimension: XY\nBounding box: xmin: -4.984872 ymin: 40.2337 xmax: 9.931386 ymax: 49.8441\nGeodetic CRS: WGS 84\nFirst 10 features:\n geometry h3\n1 POINT (1.470689 40.78258) 85394603fffffff\n2 POINT (3.65606 41.12884) 853941cbfffffff\n3 POINT (-2.451488 42.25655) 85392937fffffff\n4 POINT (6.997712 40.2337) 85394b93fffffff\n5 POINT (-4.045207 46.06162) 85184313fffffff\n6 POINT (0.4984067 43.33282) 8539663bfffffff\n7 POINT (2.457852 41.96973) 853944affffffff\n8 POINT (8.899564 41.77609) 851eb233fffffff\n9 POINT (1.249403 43.94849) 8539609bfffffff\n10 POINT (-0.7160074 40.27496) 85397223fffffff\n```\n\n\n:::\n:::\n\n\nYou can use the `st_as_sfc()` method to convert H3 hexagons to sf `POLYGON`s.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# replace geometry\nh3_cells <- pnts |>\n mutate(\n h3 = h3_from_points(geometry, 4),\n geometry = st_as_sfc(h3)\n )\n\n# plot the hexagons\nplot(st_geometry(h3_cells))\n```\n\n::: {.cell-output-display}\n![](index_files/figure-html/unnamed-chunk-1-1.png){width=672}\n:::\n:::\n\n\nH3 cell centroids can be returned using `h3_to_points()`. If `sf` is avilable,\nthe results will be returned as an `sfc` (sf column) object. Otherwise it will\nreturn a list of `sfg` (sf geometries).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# fetch h3 column\nh3s <- h3_cells[[\"h3\"]]\n\n# get there centers\nh3_centers <- h3_to_points(h3s)\n\n# plot the hexagons with the centers\nplot(st_geometry(h3_cells))\nplot(h3_centers, pch = 16, add = TRUE, col = \"black\")\n```\n\n::: {.cell-output-display}\n![](index_files/figure-html/unnamed-chunk-2-1.png){width=672}\n:::\n:::\n\n\n## H3 at light speed ⚡\n\nBecause it builds on a pure Rust implementation, `h3o` is also very very fast. \nHere are some benchmarks, which also serve to showcase `h3o` tools.\n\n### Creating polygons\n\n\n::: {.cell}\n\n```{.r .cell-code}\nh3_strs <- as.character(h3s)\nbench::mark(\n h3o = st_as_sfc(h3s),\n h3jsr = h3jsr::cell_to_polygon(h3_strs),\n relative = TRUE\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 2 × 6\n expression min median `itr/sec` mem_alloc `gc/sec`\n <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>\n1 h3o 1 1 17.2 1 1 \n2 h3jsr 18.5 17.8 1 275. 5.77\n```\n\n\n:::\n:::\n\n\n### Converting polygons to H3 cells:\n\n\n::: {.cell}\n\n```{.r .cell-code}\nnc <- st_read(system.file(\"gpkg/nc.gpkg\", package = \"sf\"), quiet = TRUE) |>\n st_transform(4326) |>\n st_geometry()\n\nbench::mark(\n h3o = sfc_to_cells(nc, 5, \"centroid\"),\n h3jsr = h3jsr::polygon_to_cells(nc, 5),\n check = FALSE,\n relative = TRUE\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 2 × 6\n expression min median `itr/sec` mem_alloc `gc/sec`\n <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>\n1 h3o 1 1 5.16 1 2.26\n2 h3jsr 5.43 5.30 1 33.7 1 \n```\n\n\n:::\n:::\n\n\n### Converting points to cells\n\n\n::: {.cell}\n\n```{.r .cell-code}\nbench::mark(\n h3o = h3_from_points(pnts$geometry, 3),\n h3jsr = h3jsr::point_to_cell(pnts$geometry, 3),\n check = FALSE,\n relative = TRUE\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 2 × 6\n expression min median `itr/sec` mem_alloc `gc/sec`\n <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>\n1 h3o 1 1 23.8 1 1.31\n2 h3jsr 26.7 26.5 1 1178. 1 \n```\n\n\n:::\n:::\n\n\n### Retrieve edges\n\n\n::: {.cell}\n\n```{.r .cell-code}\nbench::mark(\n h3o = h3_edges(h3s),\n h3jsr = h3jsr::get_udedges(h3_strs),\n check = FALSE,\n relative = TRUE\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 2 × 6\n expression min median `itr/sec` mem_alloc `gc/sec`\n <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>\n1 h3o 1 1 3.10 1 1.03\n2 h3jsr 4.00 3.26 1 7.02 1 \n```\n\n\n:::\n:::\n\n\n### Get origins and destinations from edges.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# get edges for a single location\neds <- h3_edges(h3s[1])[[1]]\n# strings for h3jsr\neds_str <- as.character(eds)\n\nbench::mark(\n h3o = h3_edge_cells(eds),\n h3jsr = h3jsr::get_udends(eds_str),\n check = FALSE,\n relative = TRUE\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 2 × 6\n expression min median `itr/sec` mem_alloc `gc/sec`\n <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>\n1 h3o 1 1 34.7 1 1.28\n2 h3jsr 45.2 35.8 1 2.52 1 \n```\n\n\n:::\n:::\n\n\n## Installation 📦\n\nYou can install the release version of `h3o` from CRAN with:\n\n``` r\ninstall.packages(\"h3o\")\n```\n\nOr you can install the development version from [GitHub](https://github.com/)\nwith:\n\n``` r\n# install.packages(\"pak\")\npak::pak(\"extendr/h3o\")\n```\n\n## Learn more 🧑‍🎓\n\nSee the package documentation for more details: <http://extendr.rs/h3o/>. \n\nIf you encounter a bug or would like to request new features, head over to the \nGitHub repository: <https://github.com/extendr/h3o>.",
6+
"supporting": [
7+
"index_files"
8+
],
9+
"filters": [
10+
"rmarkdown/pagebreak.lua"
11+
],
12+
"includes": {},
13+
"engineDependencies": {},
14+
"preserve": {},
15+
"postProcess": true
16+
}
17+
}
12.4 KB
Loading
14.6 KB
Loading
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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>.
49.5 KB
Loading

0 commit comments

Comments
 (0)