{"id":33187090,"url":"https://dieghernan.github.io/tidyterra/","last_synced_at":"2025-11-25T18:00:39.774Z","repository":{"id":36961478,"uuid":"488274429","full_name":"dieghernan/tidyterra","owner":"dieghernan","description":"tidyverse and ggplot2 methods for terra spatial objects","archived":false,"fork":false,"pushed_at":"2025-11-03T17:35:35.000Z","size":404592,"stargazers_count":208,"open_issues_count":11,"forks_count":11,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-11-13T10:06:24.668Z","etag":null,"topics":["cran","cran-r","ggplot-extension","r","r-package","r-spatial","rspatial","rstats","rstats-package","terra"],"latest_commit_sha":null,"homepage":"https://dieghernan.github.io/tidyterra/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dieghernan.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":"codemeta.json","zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"dieghernan","patreon":null,"open_collective":null,"ko_fi":"dieghernan","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2022-05-03T15:59:17.000Z","updated_at":"2025-11-03T17:35:39.000Z","dependencies_parsed_at":"2023-02-19T05:46:14.335Z","dependency_job_id":"0f002293-d7db-45a0-8c22-cae3484d1a5b","html_url":"https://github.com/dieghernan/tidyterra","commit_stats":{"total_commits":356,"total_committers":6,"mean_commits":"59.333333333333336","dds":0.151685393258427,"last_synced_commit":"8faefa0764fefd528d8fa3a59404bc358acbef1a"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/dieghernan/tidyterra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dieghernan%2Ftidyterra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dieghernan%2Ftidyterra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dieghernan%2Ftidyterra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dieghernan%2Ftidyterra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dieghernan","download_url":"https://codeload.github.com/dieghernan/tidyterra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dieghernan%2Ftidyterra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286079811,"owners_count":27282121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-25T02:00:05.816Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cran","cran-r","ggplot-extension","r","r-package","r-spatial","rspatial","rstats","rstats-package","terra"],"created_at":"2025-11-16T05:00:30.371Z","updated_at":"2025-11-25T18:00:39.769Z","avatar_url":"https://github.com/dieghernan.png","language":"R","funding_links":["https://github.com/sponsors/dieghernan","https://ko-fi.com/dieghernan"],"categories":["Spatial"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_knit$set(\n  progress = TRUE,\n  base.url = \"https://raw.githubusercontent.com/dieghernan/tidyterra/main/\"\n)\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  tidy = \"styler\",\n  comment = \"#\u003e\",\n  fig.path = \"img/README-\",\n  warning = FALSE,\n  message = FALSE,\n  dev = \"ragg_png\",\n  dpi = 300,\n  out.width = \"100%\"\n)\n```\n\n# tidyterra \u003ca href=\"https://dieghernan.github.io/tidyterra/\"\u003e\u003cimg src=\"man/figures/logo.png\" align=\"right\" height=\"139\"/\u003e\u003c/a\u003e\n\n\u003c!-- badges: start --\u003e\n\n[![CRAN\nstatus](https://www.r-pkg.org/badges/version/tidyterra)](https://CRAN.R-project.org/package=tidyterra)\n[![CRAN\nresults](https://badges.cranchecks.info/worst/tidyterra.svg)](https://cran.r-project.org/web/checks/check_results_tidyterra.html)\n[![Downloads](https://cranlogs.r-pkg.org/badges/tidyterra)](https://CRAN.R-project.org/package=tidyterra)\n[![DOI](https://joss.theoj.org/papers/10.21105/joss.05751/status.svg)](https://doi.org/10.21105/joss.05751)\n[![R-CMD-check](https://github.com/dieghernan/tidyterra/actions/workflows/check-full.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/check-full.yaml)\n[![R-hub](https://github.com/dieghernan/tidyterra/actions/workflows/rhub.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/rhub.yaml)\n[![codecov](https://codecov.io/gh/dieghernan/tidyterra/branch/main/graph/badge.svg?token=blvDmRjcfb)](https://app.codecov.io/gh/dieghernan/tidyterra)\n[![CodeFactor](https://www.codefactor.io/repository/github/dieghernan/tidyterra/badge)](https://www.codefactor.io/repository/github/dieghernan/tidyterra)\n[![r-universe](https://dieghernan.r-universe.dev/badges/tidyterra)](https://dieghernan.r-universe.dev/tidyterra)\n[![Project Status: Active -- The project has reached a stable, usable state and\nis being actively\ndeveloped.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)\n[![Stack Exchange\nquestions](https://img.shields.io/stackexchange/stackoverflow/t/tidyterra?logo=stackoverflow\u0026label=stackoverflow%20q%26a)](https://stackoverflow.com/questions/tagged/tidyterra)\n[![Works with\nterra-devel](https://github.com/dieghernan/tidyterra/actions/workflows/check-terra-devel.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/check-terra-devel.yaml)\n[![Works with\nsf-devel](https://github.com/dieghernan/tidyterra/actions/workflows/check-sf-devel.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/check-sf-devel.yaml)\n[![Works with\nggplot2-devel](https://github.com/dieghernan/tidyterra/actions/workflows/check-ggplot2-devel.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/check-ggplot2-devel.yaml)\n[![Works with dplyr and\nreadr-devel](https://github.com/dieghernan/tidyterra/actions/workflows/check-dplyr-readr.yaml/badge.svg)](https://github.com/dieghernan/tidyterra/actions/workflows/check-dplyr-readr.yaml)\n\n\u003c!-- badges: end --\u003e\n\nThe goal of **tidyterra** is to provide common methods of the [**tidyverse**\npackages](https://tidyverse.org/packages/) for objects created with the\n[**terra**](https://CRAN.R-project.org/package=terra) package: `SpatRaster` and\n`SpatVector`. It also provides `geoms` for plotting these objects with\n[**ggplot2**](https://ggplot2.tidyverse.org/).\n\nPlease cite **tidyterra** as:\n\n\u003e Hernangómez, D., (2023). Using the tidyverse with terra objects: the tidyterra\n\u003e package. *Journal of Open Source Software*, *8*(91), 5751,\n\u003e \u003chttps://doi.org/10.21105/joss.05751\u003e.\n\nA BibTeX entry for LaTeX users is:\n\n``` bib\n@article{Hernangómez2023,\n  doi = {10.21105/joss.05751},\n  url = {https://doi.org/10.21105/joss.05751},\n  year = {2023},\n  publisher = {The Open Journal},\n  volume = {8},\n  number = {91},\n  pages = {5751},\n  author = {Diego Hernangómez},\n  title = {Using the {tidyverse} with {terra} objects: the {tidyterra} package},\n  journal = {Journal of Open Source Software}\n}\n```\n\n## Overview\n\nFull manual of the most recent release of **tidyterra** on **CRAN** is online:\n\u003chttps://dieghernan.github.io/tidyterra/\u003e\n\n**tidyverse** methods implemented on **tidyterra** works differently depending\non the type of `Spat*` object:\n\n-   `SpatVector`: the methods are implemented using `terra::as.data.frame()`\n    coercion. Rows correspond to geometries and columns correspond to attributes\n    of the geometry.\n\n-   `SpatRaster`: The implementation on `SpatRaster` objects differs, since the\n    methods could be applied to layers or to cells. **tidyterra** overall\n    approach is to treat the layers as columns of a tibble and the cells as rows\n    (i.e. `select(SpatRaster, 1)` would select the first layer of a\n    `SpatRaster`).\n\nThe methods implemented return the same type of object used as input, unless the\nexpected behavior of the method is to return another type of object, (for\nexample, `as_tibble()` would return a `tibble`).\n\nCurrent methods and functions provided by **tidyterra** are:\n\n| tidyverse method | `SpatVector` | `SpatRaster` |\n|----|----|----|\n| `tibble::as_tibble()` | ✔️ | ✔️ |\n| `dplyr::select()` | ✔️ | ✔️ Select layers |\n| `dplyr::mutate()` | ✔️ | ✔️ Create /modify layers |\n| `dplyr::transmute()` | ✔️ | ✔️ |\n| `dplyr::filter()` | ✔️ | ✔️ Modify cells values and (additionally) remove outer cells. |\n| `dplyr::slice()` | ✔️ | ✔️ Additional methods for slicing by row and column. |\n| `dplyr::pull()` | ✔️ | ✔️ |\n| `dplyr::rename()` | ✔️ | ✔️ |\n| `dplyr::relocate()` | ✔️ | ✔️ |\n| `dplyr::distinct()` | ✔️ |  |\n| `dplyr::arrange()` | ✔️ |  |\n| `dplyr::glimpse()` | ✔️ | ✔️ |\n| `dplyr::inner_join()` family | ✔️ |  |\n| `dplyr::summarise()` | ✔️ |  |\n| `dplyr::group_by()` family | ✔️ |  |\n| `dplyr::rowwise()` | ✔️ |  |\n| `dplyr::count()`, `tally()` | ✔️ |  |\n| `dplyr::bind_cols()` / `dplyr::bind_rows()` | ✔️ as `bind_spat_cols()` / `bind_spat_rows()` |  |\n| `tidyr::drop_na()` | ✔️ | ✔️ Remove cell values with `NA` on any layer. Additionally, outer cells with `NA` are removed. |\n| `tidyr::replace_na()` | ✔️ | ✔️ |\n| `tidyr::fill()` | ✔️ |  |\n| `tidyr::pivot_longer()` | ✔️ |  |\n| `tidyr::pivot_wider()` | ✔️ |  |\n| `ggplot2::autoplot()` | ✔️ | ✔️ |\n| `ggplot2::fortify()` | ✔️ to **sf** via `sf::st_as_sf()` | To a **tibble** with coordinates. |\n| `ggplot2::geom_*()` | ✔️ `geom_spatvector()` | ✔️ `geom_spatraster()` and `geom_spatraster_rgb()`. |\n| `generics::tidy()` | ✔️ | ✔️ |\n| `generics::glance()` | ✔️ | ✔️ |\n| `generics::required_pkgs()` | ✔️ | ✔️ |\n\n## :exclamation: A note on performance\n\n**tidyterra** is conceived as a user-friendly wrapper of **terra** using the\n**tidyverse** methods and verbs. This approach therefore has a **cost in terms\nof performance**.\n\nIf you are a **heavy user** of **terra** or you need to work with **big raster\nfiles**, **terra** is much more focused on terms of performance. When possible,\neach function of **tidyterra** references to its equivalent on **terra**.\n\nAs a rule of thumb if your raster has less than 10.000.000 data slots counting\ncells and layers (i.e. `terra::ncell(your_rast)*terra::nlyr(your_rast) \u003c 10e6`)\nyou are good to go with **tidyterra**.\n\nWhen plotting rasters, resampling is performed automatically (as `terra::plot()`\ndoes, see the help page). You can adjust this with the `maxcell` parameter.\n\n## Installation\n\nInstall **tidyterra** from\n[**CRAN**](https://CRAN.R-project.org/package=tidyterra):\n\n```{r, eval=FALSE}\ninstall.packages(\"tidyterra\")\n```\n\nYou can install the development version of **tidyterra** like so:\n\n```{r, eval=FALSE }\n# install.packages(\"pak\")\npak::pak(\"dieghernan/tidyterra\")\n```\n\nAlternatively, you can install **tidyterra** using the\n[r-universe](https://dieghernan.r-universe.dev/tidyterra):\n\n```{r, eval=FALSE}\n# Enable this universe\ninstall.packages(\"tidyterra\", repos = c(\n  \"https://dieghernan.r-universe.dev\",\n  \"https://cloud.r-project.org\"\n))\n```\n\n## Example\n\n### `SpatRasters`\n\nThis is a basic example which shows you how to manipulate and plot `SpatRaster`\nobjects:\n\n```{r example-temp}\nlibrary(tidyterra)\nlibrary(terra)\n\n# Temperatures\nrastertemp \u003c- rast(system.file(\"extdata/cyl_temp.tif\", package = \"tidyterra\"))\n\nrastertemp\n\n# Rename\nrastertemp \u003c- rastertemp %\u003e%\n  rename(April = tavg_04, May = tavg_05, June = tavg_06)\n\n# Facet all layers\nlibrary(ggplot2)\n\nggplot() +\n  geom_spatraster(data = rastertemp) +\n  facet_wrap(~lyr, ncol = 2) +\n  scale_fill_whitebox_c(\n    palette = \"muted\",\n    labels = scales::label_number(suffix = \"º\"),\n    n.breaks = 12,\n    guide = guide_legend(reverse = TRUE)\n  ) +\n  labs(\n    fill = \"\",\n    title = \"Average temperature in Castille and Leon (Spain)\",\n    subtitle = \"Months of April, May and June\"\n  )\n\n# Create maximum differences of two months\nvariation \u003c- rastertemp %\u003e%\n  mutate(diff = June - May) %\u003e%\n  select(variation = diff)\n\n# Add also a overlay of a SpatVector\nprov \u003c- vect(system.file(\"extdata/cyl.gpkg\", package = \"tidyterra\"))\n\nggplot(prov) +\n  geom_spatraster(data = variation) +\n  geom_spatvector(fill = NA) +\n  scale_fill_whitebox_c(\n    palette = \"deep\", direction = -1,\n    labels = scales::label_number(suffix = \"º\"),\n    n.breaks = 5\n  ) +\n  theme_minimal() +\n  coord_sf(crs = 25830) +\n  labs(\n    fill = \"Variation\",\n    title = \"Variation of Temperature in Castile and León (Spain)\",\n    subtitle = \"Average Temperatures: June vs. May\"\n  )\n```\n\n**tidyterra** also provides a geom for plotting RGB `SpatRaster` tiles with\n**ggplot2**:\n\n```{r example-tile}\nrgb_tile \u003c- rast(system.file(\"extdata/cyl_tile.tif\", package = \"tidyterra\"))\n\nplot \u003c- ggplot(prov) +\n  geom_spatraster_rgb(data = rgb_tile) +\n  geom_spatvector(fill = NA) +\n  theme_light()\n\nplot\n\n# Automatically recognizes and applies coord_sf() for spatial data.\nplot +\n  # Change the CRS and datum (useful for relabeling graticules).\n  coord_sf(crs = 3857, datum = 3857)\n```\n\n**tidyterra** provides specific scales for plotting hypsometric maps with\n**ggplot2**:\n\n```{r hypso, fig.asp=0.65}\nasia \u003c- rast(system.file(\"extdata/asia.tif\", package = \"tidyterra\"))\n\nterra::plot(asia)\n\nggplot() +\n  geom_spatraster(data = asia) +\n  scale_fill_hypso_tint_c(\n    palette = \"gmt_globe\",\n    labels = scales::label_number(),\n    # Further refinements\n    breaks = c(-10000, -5000, 0, 2000, 5000, 8000),\n    guide = guide_colorbar(reverse = TRUE)\n  ) +\n  labs(\n    fill = \"elevation (m)\",\n    title = \"Hypsometric map of Asia\"\n  ) +\n  theme(\n    legend.position = \"bottom\",\n    legend.title.position = \"top\",\n    legend.key.width = rel(3),\n    legend.ticks = element_line(colour = \"black\", linewidth = 0.3),\n    legend.direction = \"horizontal\"\n  )\n```\n\n### `SpatVectors`\n\nThis is a basic example which shows you how to manipulate and plot `SpatVector`\nobjects:\n\n```{r spatvec }\nvect(system.file(\"ex/lux.shp\", package = \"terra\")) %\u003e%\n  mutate(pop_dens = POP / AREA) %\u003e%\n  glimpse() %\u003e%\n  autoplot(aes(fill = pop_dens)) +\n  scale_fill_whitebox_c(palette = \"pi_y_g\") +\n  labs(\n    fill = \"population per km2\",\n    title = \"Population density of Luxembourg\",\n    subtitle = \"By canton\"\n  )\n```\n\n## I need your feedback\n\nPlease leave your feedback or open an issue on\n\u003chttps://github.com/dieghernan/tidyterra/issues\u003e.\n\n## Need help?\n\nCheck our [FAQs](https://dieghernan.github.io/tidyterra/articles/faqs.html) or\nopen a new [issue](https://github.com/dieghernan/tidyterra/issues)!\n\nYou can also ask in [Stack Overflow](https://stackoverflow.com/) using the tag\n[[tidyterra]](https://stackoverflow.com/questions/tagged/tidyterra).\n\n## Acknowledgement\n\n**tidyterra** **ggplot2** geoms are based on\n[**ggspatial**](https://github.com/paleolimbot/ggspatial) implementation, by\n[Dewey Dunnington](https://github.com/paleolimbot) and [**ggspatial**\ncontributors](https://github.com/paleolimbot/ggspatial/graphs/contributors).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/dieghernan.github.io%2Ftidyterra%2F","html_url":"https://awesome.ecosyste.ms/projects/dieghernan.github.io%2Ftidyterra%2F","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/dieghernan.github.io%2Ftidyterra%2F/lists"}