Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"hash": "6119954e7cd9d2742a652929e32451c6",
"hash": "0e2ac93c67c7c976145259a04d7c7571",
"result": {
"engine": "knitr",
"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>.",
"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: \n - name: Blake Vernon\n - name: Josiah Parry\ndate: \"2025/09/09\"\nimage: thumbnail.png\nimage-alt: \"The letters h3o on a hexagonal sticker.\"\ncategories: [Release]\n---\n\n\n\n![](thumbnail.png)\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\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\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\nmutate(pnts, 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.861231 ymin: 40.05397 xmax: 9.846006 ymax: 49.98446\nGeodetic CRS: WGS 84\nFirst 10 features:\n geometry h3\n1 POINT (3.169478 45.06344) 851f92d7fffffff\n2 POINT (5.63995 44.91631) 851f9323fffffff\n3 POINT (1.263684 42.55526) 85396207fffffff\n4 POINT (0.3876174 41.06653) 853973b3fffffff\n5 POINT (-1.192501 44.22128) 85184d7bfffffff\n6 POINT (3.86172 41.56535) 8539419bfffffff\n7 POINT (-1.565639 49.98446) 851866bbfffffff\n8 POINT (3.704704 42.74759) 85396e47fffffff\n9 POINT (2.804652 47.0575) 851fb267fffffff\n10 POINT (-4.021278 47.52185) 851846affffffff\n```\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\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\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\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\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\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 26.1 1 1 \n2 h3jsr 27.0 25.6 1 268. 3.85\n```\n\n\n:::\n:::\n\n\n\n### Converting polygons to H3 cells:\n\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 7.79 1 5.84\n2 h3jsr 8.96 7.82 1 33.0 1 \n```\n\n\n:::\n:::\n\n\n\n### Converting points to cells\n\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 16.8 1 1.02\n2 h3jsr 16.7 19.4 1 1193. 1 \n```\n\n\n:::\n:::\n\n\n\n### Retrieve edges\n\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 2.95 1 1 \n2 h3jsr 2.97 2.83 1 7.02 2.65\n```\n\n\n:::\n:::\n\n\n\n### Get origins and destinations from edges.\n\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 24.6 1 1 \n2 h3jsr 21.3 26.1 1 2.52 3.01\n```\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>.",
"supporting": [
"index_files"
],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion blog/posts/2025-09-09-h3o-on-cran/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ image-alt: "The letters h3o on a hexagonal sticker."
categories: [Release]
---

![](thumbnail.png)

The extendr-powered R package `h3o` provides access to [a pure Rust implementation](https://github.com/HydroniumLabs/h3o)
of [Uber's H3 Geospatial Indexing System](https://github.com/uber/h3).
Originally developed by Josiah Parry, the R package has also become an official
product of extendr, which means community support 🤝 and maintenance 🏗️ into
the foreseeable future.


## `h3o` at a glance 👀

The package provides functionality to interact with H3's grid as vectors, which
Expand All @@ -43,7 +46,7 @@ pnts <- st_as_sf(
crs = 4326
)

pnts |> mutate(h3 = h3_from_points(geometry, 5))
mutate(pnts, h3 = h3_from_points(geometry, 5))
```

You can use the `st_as_sfc()` method to convert H3 hexagons to sf `POLYGON`s.
Expand Down