{"id":19881458,"url":"https://github.com/giscience/ohsome-r","last_synced_at":"2025-05-02T14:30:46.659Z","repository":{"id":46658303,"uuid":"382331549","full_name":"GIScience/ohsome-r","owner":"GIScience","description":"This ohsome R package grants access to the power of the ohsome API from R.","archived":false,"fork":false,"pushed_at":"2023-10-04T14:50:40.000Z","size":17055,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-04-09T15:12:03.789Z","etag":null,"topics":["heigit","ohsome","openstreetmap","openstreetmap-data","openstreetmap-history","osm","osm-data"],"latest_commit_sha":null,"homepage":"https://ohsome.org","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GIScience.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-02T11:55:38.000Z","updated_at":"2024-04-09T15:12:03.790Z","dependencies_parsed_at":"2023-01-24T04:46:56.130Z","dependency_job_id":null,"html_url":"https://github.com/GIScience/ohsome-r","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fohsome-r","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fohsome-r/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fohsome-r/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GIScience%2Fohsome-r/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GIScience","download_url":"https://codeload.github.com/GIScience/ohsome-r/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224315203,"owners_count":17290992,"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","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":["heigit","ohsome","openstreetmap","openstreetmap-data","openstreetmap-history","osm","osm-data"],"created_at":"2024-11-12T17:14:19.723Z","updated_at":"2024-11-12T17:14:20.515Z","avatar_url":"https://github.com/GIScience.png","language":"R","funding_links":[],"categories":[],"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_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\", \n  out.width = 900\n)\n```\n\n# ohsome: An R package to interact with the ohsome API for OpenStreetMap history data aggregation and extraction\n\n\u003c!-- badges: start --\u003e\n[![LICENSE](https://img.shields.io/github/license/GIScience/ohsome-r)](https://github.com/GIScience/ohsome-r/blob/main/LICENSE.md)\n[![status: active](https://github.com/GIScience/badges/raw/master/status/active.svg)](https://github.com/GIScience/badges#active)\n![CRAN status](https://www.r-pkg.org/badges/version-ago/ohsome)\n\u003c!-- badges: end --\u003e\n\nThis ohsome R package grants access to the power of the [ohsome API](https://api.ohsome.org){target=blank}\nfrom R. ohsome lets you analyze the rich data source of the\n[OpenStreetMap](https://www.openstreetmap.org/){target=blank} \n(OSM) history. It aims to leverage the tools of the \n[OpenStreetMap History Database](https://github.com/GIScience/oshdb){target=blank}\n(OSHDB).\n\nWith ohsome, you can ...\n\n- Get **aggregated statistics** on the evolution of OpenStreetMap elements and\nspecify your own temporal, spatial and/or thematic filters. The data aggregation \nendpoint allows you to access functions, e.g., to calculate the area of \nbuildings or the length of streets at any given timestamp.\n\n- Retrieve the **geometry** of the historical OpenStreetMap data, e.g., to\nvisualize the evolution of certain OpenStreetMap elements over time. You can get\nthe geometries for specific points in time or all changes within a timespan \n(full-history).\n\n \n## Installation\n\nYou can install ohsome from \n[CRAN](https://CRAN.R-project.org/package=ohsome){target=blank} or from\n[GitHub](https://github.com/GIScience/ohsome-r){target=blank}:\n\n```{r, eval = FALSE}\ninstall.packages(\"ohsome\")\nremotes::install_github(\"GIScience/ohsome-r\", ref = \"main\")\n\n```\n\n## Getting started\n\nUpon attaching the ohsome package, a metadata request is sent to the ohsome \nAPI. The package message provides some essential metadata information, such as\nthe current temporal extent of the underlying OSHDB:\n\n```{r library}\nlibrary(ohsome)\n```\n\nThe metadata is stored in `ohsome_metadata`. You can print it to the console\nto get more details.\n\nYou can create any ohsome API query using the generic `ohsome_query()` function. \nIt takes the endpoint path and any query parameters as inputs. For information \non all available endpoints with their parameters, consult the \n[ohsome API documentation](https://docs.ohsome.org/ohsome-api/stable/endpoints.html){target=blank} \nor print `ohsome_endpoints` to the console.\n\nHowever, this ohsome R package provides specific wrapper functions for queries \nto all available endpoints.\n\n### OSM elements\n\n#### Aggregating OSM elements\n\nThe\n[elements aggregation endpoints](https://docs.ohsome.org/ohsome-api/stable/endpoints.html#elements-aggregation){target=blank}\nof the ohsome API allow querying for the aggregated amount, length, area or \nperimeter of OpenStreetMap elements with given properties, within given \nboundaries and at given points in time.\n\nLet us create a query for the total amount of breweries on OSM in the region of \nFranconia. The first argument to `ohsome_elements_count()` is the `sf` object \n`franconia` that is included in the \n[mapview](https://r-spatial.github.io/mapview/){target=blank} \npackage and contains boundary \npolygons of the `r nrow(mapview::franconia)` districts of the region:\n\n```{r fix, include = FALSE}\n# avoid messages when handling franconia with old-style crs object\nfranconia \u003c- sf::st_set_crs(mapview::franconia, 4326)\n```\n\n```{r elements_count}\nlibrary(mapview)\n\nq \u003c- ohsome_elements_count(franconia, filter = \"craft=brewery\")\n```\n\nThe resulting `ohsome_query` object can be sent to the ohsome API with\n`ohsome_post()`. By default, `ohsome_post()` returns the parsed API\nresponse. In this case, this is a simple `data.frame` of only one row.\n\n```{r post}\nohsome_post(q, strict = FALSE)\n``` \n\nThe `ohsome_query` object was created without an explicit `time` parameter. When\nusing functions to create element aggregation queries, `time` defaults to the \nmost recent available timestamp in the underlying OSHDB.^[`ohsome_post` fails on \nqueries created with an undefined `time` parameter unless strict query \nvalidation is disabled with `strict = FALSE`.]\n\nDefining the `time` parameter unlocks the full power of ohsome API by giving \naccess to the OSM history. It requires one or more \n[ISO-8601 conform timestring(s)](https://docs.ohsome.org/ohsome-api/stable/time.html){target=blank}.\nHere is how to create a query for the number of breweries at the first of each \nmonth between 2010 and 2020:\n\n```{r time, eval = FALSE}\nohsome_elements_count(franconia, filter = \"craft=brewery\", time = \"2010/2020/P1M\")\n```\n\nAlternatively, we can update the existing `ohsome_query` object `q` with the \n`set_time()` function, \npipe ^[Instead of the new R native pipe `|\u003e` you may choose to use `magrittr`'s `%\u003e%`.]\nthe modified query directly into `ohsome_post()` \nand make a quick visualization with `ggplot2`:\n\n```{r pipe, dev = \"svg\"}\nlibrary(ggplot2)\n\nq |\u003e \n\tset_time(\"2010/2020/P1M\") |\u003e\n\tohsome_post() |\u003e\n\tggplot(aes(x = timestamp, y = value)) +\n\tgeom_line()\n```\n\nThis is how to query the total number of breweries in all of Franconia. But\nwhat if we want to aggregate the amount per district? The ohsome API provides \nspecific endpoints for different grouped calculations, such as aggregation \ngrouped by bounding geometry.\n\nThere are several ways to define a query for an aggregation grouped by boundary:\n\nThe `set_endpoint`function is used to change or append the endpoint path of an \nAPI request. In this case, we could append `groupBy/boundary` to the existing \nquery to the `elements/count` endpoint. The endpoint path can either be given \nas a single string (`/groupBy/boundary`) or as a character vector: \n`set_endpoint(q, c(\"groupBy\", \"boundary\"), append = TRUE)` \n^[The order of the elements in the character vector is critical!].\n\nMore comfortable, however, is the use of either the grouping argument with an\nelements aggregation function (e.g. \n`ohsome_elements_count(grouping = \"boundary)`) or of the `set_grouping()` \nfunction to modify an existing query object:\n\n```{r groupBy_boundary, message = FALSE}\nlibrary(dplyr)\n\nfranconia |\u003e \n\tmutate(id = NAME_ASCI) |\u003e\n\tohsome_elements_count(filter = \"craft=brewery\", time = \"2021-06-01\") |\u003e\n\tset_grouping(\"boundary\") |\u003e\n\tohsome_post()\n```\n\nIf you want your own identifiers for the geometries returned by ohsome, your \ninput `sf` object needs a column explicitly named `id`. You can use `mutate()` \nor `rename()` from the \n[dplyr](https://dplyr.tidyverse.org){target=blank} \npackage to create such a column as in the example\nbelow.\n\nBy default, `ohsome_post()` returns an `sf` object whenever the ohsome API \nis capable of delivering GeoJSON data. This is the case for elements \nextraction queries as well as for aggregations grouped by boundaries.\n\nThus, you can easily create a choropleth map from the query results.\nIn addition, you can set the argument `return_value` to `density`. This will \nmodify the endpoint path of the query so that ohsome returns the number of \nbreweries per area instead of the absolute value:\n\n```{r density}\nfranconia |\u003e \n\tmutate(id = NAME_ASCI) |\u003e\n\tohsome_elements_count(filter = \"craft=brewery\", return_value = \"density\") |\u003e\n\tset_time(\"2021-06-01\") |\u003e\n\tset_grouping(\"boundary\") |\u003e\n\tohsome_post() |\u003e\n\tmapview(zcol = \"value\", layer.name = \"Breweries per sqkm\")\n```\n\n#### Extracting OSM elements\n\nThe\n[elements extraction endpoints](https://docs.ohsome.org/ohsome-api/stable/endpoints.html#elements-extraction){target=blank}\nof the ohsome API allow obtaining geometries, bounding boxes or centroids of OSM\nelements with given properties, within given boundaries and at given points in \ntime. Together with the elements, you can choose to query for their tags and/or \ntheir metadata such as the changeset ID, the time of the last edit or the \nversion number.\n\nThe following query extracts the geometries of buildings within 1000 m of \nHeidelberg main station with their tags. The response is used to visualize\nthe buildings and the values of their `building:levels` tag (if available):\n\n```{r building_levels, warning = FALSE}\nhd_station_1km \u003c- ohsome_boundary(\"8.67542,49.40347,1000\")\n\nohsome_elements_geometry(\n\tboundary = hd_station_1km, \n\tfilter = \"building=* and type:way\", \n\ttime = \"2021-12-01\",\n\tproperties = \"tags\", \n\tclipGeometry = FALSE\n) |\u003e\n\tohsome_post() |\u003e\n\ttransmute(level = factor(`building:levels`)) |\u003e\n\tmapview(zcol = \"level\", lwd = 0, layer.name = \"Building level\")\n```\n\nSimilarly, you can use `ohsome_elements_centroid()` to extract centroids of OSM\nelements and `ohsome_elements_bbox()` for their bounding boxes. Note that OSM\nnode elements (with point geometries) are omitted from the results if querying \nfor bounding boxes.\n\n\n#### Extracting the full history of OSM elements\n\nWhile the elements extraction endpoints provide geometries and properties of OSM \nelements at specific timestamps, results of queries to the \n[full history endpoints](https://docs.ohsome.org/ohsome-api/v1/endpoints.html#elements-full-history-extraction){target=blank}\nwill include all changes to matching OSM features with corresponding \n`validFrom` and `validTo` timestamps.\n\nHere, we request the full history of OSM buildings within 1000 m of Heidelberg\nmain station, filter for features that still exist and visualize all building \nfeatures with their year of creation:\n\n```{r buildings, eval = F}\nmeta \u003c- ohsome_get_metadata()\nstart \u003c- meta$extractRegion$temporalExtent[1]\nend \u003c- \"2023-01-01\"\n\nohsome_elementsFullHistory_geometry(\n\tboundary = hd_station_1km,\n\ttime = c(start, end),\n\tfilter = \"building=* and geometry:polygon\", \n\tclipGeometry = FALSE,\n\tproperties = \"metadata\"\n) |\u003e \n\tohsome_post() |\u003e\n\tjanitor::clean_names() |\u003e\n\tgroup_by(osm_id) |\u003e\n\tmutate(year = min(format(valid_from, \"%Y\"))) |\u003e\n\tfilter(valid_to == lubridate::ymd(end)) |\u003e\n\tmapview(zcol = \"year\", lwd = 0, layer.name = \"Year of Feature Creation\")\n```\n\nYou may find using `clean_names()` from the \n[janitor](https://github.com/sfirke/janitor){target=blank} \npackage helpful in order to remove special characters from column names in the \nparsed ohsome API response -- just as in the example above.\n\n### OSM contributions\n\n#### Aggregating OSM contributions\n\nWith queries to the ohsome API's\n[contributions aggregation endpoints](https://docs.ohsome.org/ohsome-api/v1/endpoints.html#contributions-aggregation){target=blank},\nyou can get counts of the contributions provided by users to OSM. The following \ncode requests the number of deletions of man-made objects at the location \nof the hypothetical \n[Null Island](https://en.wikipedia.org/wiki/Null_Island){target=blank}\nper year between 2010 and 2020: \n\n```{r contribution_count}\nohsome_contributions_count(\n\tboundary = \"0,0,10\", \n\tfilter = \"man_made=*\", \n\ttime = \"2010/2020/P1Y\",\n\tcontributionType = \"deletion\"\n) |\u003e\n\tohsome_post()\n```\n\nThe `contributionType` parameter is used to filter for specific types of \ncontributions (in this case: deletions). If it is not set, any contribution is \ncounted. Note that the resulting values apply to time intervals defined by a \n`fromTimestamp` and a `toTimestamp`.\n\n#### Extracting OSM contributions\n\nThe \n[contributions extraction](https://docs.ohsome.org/ohsome-api/v1/endpoints.html#contributions-extraction){target=blank}\nendpoints of the ohsome API can be used to extract feature geometries of \ncontributions.\n\nIn the following example, we extract the centroids of all amenities in the \nBerlin city district of Neukölln that have had contributions in March 2020. \nConsequently, we filter for features that have had tags changed and visualize \ntheir locations:\n\n```{r contribution_extraction}\nnominatimlite::geo_lite_sf(\"Berlin Neukoelln\", points_only = FALSE) |\u003e\n\tohsome_contributions_centroid() |\u003e\n\tset_filter(\"amenity=*\") |\u003e\n\tset_time(\"2020-03,2020-04\") |\u003e\n\tset_properties(\"contributionTypes\") |\u003e \n\tohsome_post() |\u003e\n\tfilter(`@tagChange`) |\u003e\n\tmapview(layer.name = \"Amenities with Tag Changes\")\n```\n\n### OSM users\n\nYou can get statistics on the number of users editing specific features through\nthe \n[users aggregation](https://docs.ohsome.org/ohsome-api/v1/endpoints.html#users-aggregation){target=blank}\nendpoints of the ohsome API.\n\nHere, we show the number of users editing buildings before, during and after \nthe Nepal earthquake 2015:\n\n```{r nepal}\nohsome_users_count(\n\tboundary = \"82.3055,6.7576,87.4663,28.7025\",\n\tfilter = \"building=* and geometry:polygon\",\n\ttime = \"2015-03-01/2015-08-01/P1M\"\n) |\u003e\n\tohsome_post()\n```\n\n### Bounding geometries\n\nThe ohsome API requires bounding geometries either as bounding polygons \n(`bpolys`), bounding boxes (`bboxes`) or bounding circles (`bcircles`) \nparameters to the query in a textual form (see\n[ohsome API documentation](https://docs.ohsome.org/ohsome-api/stable/boundaries.html){target=blank}).\nThe ohsome R package uses the generic function `ohsome_boundary()` under the \nhood to make your life easier. It accepts a wider range of input geometry \nformats, while guessing the right type of bounding geometry.\n\nAs seen above, `sf` objects can be passed into the `boundary` argument of \n`ohsome_query()` and any of its wrapper functions. You can also update queries \nwith `set_boundary()`. The `sf` object will be converted into GeoJSON and passed \ninto the `bpolys` parameter of the query.\n\nIf you wish to aggregate or extract OSM elements on administrative boundaries in\nthe `sf` format, you might want to check out packages such as \n[rnaturalearth](https://github.com/ropensci/rnaturalearth){target=blank}, \n[geodata](https://github.com/rspatial/geodata){target=blank},\n[raster](https://github.com/rspatial/raster){target=blank} \n(in particular its `getData()` function), \n[rgeoboundaries](https://gitlab.com/dickoa/rgeoboundaries){target=blank} or \n[nominatimlite](https://github.com/dieghernan/nominatimlite){target=blank} \nfor the acquisition of boundary data that can be used with \n`ohsome_boundary()`.\n\nThere are also the following methods of `ohsome_boundary()` for other classes\nof input geometry objects:\n\n1. `bbox` objects created with `st_bbox` are converted into a textual `bboxes` \nparameter to the query:\n\n```{r bbox}\nq \u003c- ohsome_query(\"users/count\") |\u003e\n\tset_boundary(sf::st_bbox(franconia))\n\nq$body$bboxes\n```\n\n2. `matrix` objects created with `sp::bbox()`, `raster::bbox()` or \n`terra::bbox()` are also converted into a textual `bboxes` parameter. This even \napplies for matrices created with `osmdata::getbb()` and `tmaptools::bb()`, so \nthat you can comfortably acquire bounding boxes from the Nominatim API:\n\n```{r getbb}\nosmdata::getbb(\"Kigali\") |\u003e \n\tohsome_elements_length(time = \"2018/2018-12/P1M\", filter = \"route=bus\") |\u003e\n\tohsome_post()\n```\n\n3. You can pass any `character` object with text in the \n[format allowed by the ohsome API](https://docs.ohsome.org/ohsome-api/stable/boundaries.html){target=blank}\nto `ohsome_boundary()` -- even GeoJSON FeatureCollections. It will automatically \ndetect whether you have passed the definition of `bpolys`, `bboxes` or \n`bcircles`. It is possible to use `character` vectors where each element \nrepresents one geometry:\n\n```{r circles}\nc(\"Circle 1:8.6528,49.3683,1000\", \"Circle 2:8.7294,49.4376,1000\") |\u003e\n\tohsome_elements_count(filter = \"amenity=*\", grouping = \"boundary\", time = 2021) |\u003e\n\tohsome_post()\n```\n\n`r emo::ji(\"warning\")` While `sf` and `bbox` objects will be automatically \ntransformed to WGS 84 if in a different coordinate reference system, coordinates\nin `character` and `matrix` objects always need to be provided as WGS 84.\n\n### Modifying queries\n\nAs seen above, existing `ohsome_query` objects can be modified by \n`set_endpoint()`, `set_grouping()`, `set_boundary()` or `set_time()`. The latter \nand other functions such as `set_filter()` are just wrappers around the more \ngeneric `set_parameters()`. This can be used to modify the parameters of a query \nin any possible way:\n\n```{r set_parameters}\nq \u003c- ohsome_elements_count(\"8.5992,49.3567,8.7499,49.4371\")\n\nq |\u003e\n\tset_endpoint(\"ratio\", append = TRUE) |\u003e\n\tset_parameters(\n\t\tfilter = \"building=*\", \n\t\tfilter2 = \"building=* and building:levels=*\",\n\t\ttime = \"2010/2020/P2Y\"\n\t) |\u003e\n\tohsome_post()\n\n```\n\n### Grouping\n\n[Grouping endpoints](https://docs.ohsome.org/ohsome-api/v1/group-by.html){target=blank}\nare available for aggregation resources and can be used to compute the \naggregated results grouped by:\n\n- boundary,\n- key,\n- tag, and\n- type.\n\nIn many cases, a grouping by `boundary` can be combined with a grouping by `tag`. \nSome of the grouping endpoints require additional query parameters, e.g. `tag`\ngroupings require a `groupByKey` parameter. Not all grouping endpoints are \navailable for all aggregation resources --  please consult the\n[ohsome API documentation](https://docs.ohsome.org/ohsome-api/v1/group-by.html){target=blank}\nfor details.\n\nYou can set the `grouping` argument to any aggregation endpoint wrapper function \n(e.g. `ohsome_elements_count(grouping = c(\"boundary\", \"tag\"))`) or use \n`set_grouping()` to modify existing query objects. \n\n### Density and ratio requests\n\nMany \n[aggregation resources](https://docs.ohsome.org/ohsome-api/v1/endpoints.html){target=blank}\nhave endpoints for requesting density (i.e. count, length, perimeter or area of\nfeatures **per area**) or ratios (of OSM elements satisfying a `filter2` to elements \nsatisfying a `filter`) instead of or in addition to absolute values.\n\nYou can request density or ratio values by setting the `return_value` argument\nto aggregation endpoint wrapper functions (e.g. \n`ohsome_elements_count(return_value = \"density\")`). Mind that ratio endpoints \nrequire an additional `filter2` query parameter. Please consult the \n[ohsome API documentation](https://docs.ohsome.org/ohsome-api/v1/endpoints.html){target=blank}\nor print `names(ohsome_endpoints)` to the console in order to check for the \navailability of specific density and ratio endpoints.\n\n### Dealing with complex API responses\n\nThe ohsome API allows grouping aggregate values for various timestamps by \nboundary and tag at the same time. The parsed content of the response can be \nrather complex. In the following case, building feature counts for the districts \nof Franconia at two different timestamps are requested -- additionally grouped \nby the building:levels tag. To avoid lots of redundant geometries, \ncomma-separated values (instead of GeoJSON) are explicitly requested as the \nresponse format:\n\n```{r groupby_boundary_groupby_tag, message = FALSE}\nbuilding_levels \u003c- franconia |\u003e\n\tmutate(id  = NUTS_ID) |\u003e\n\tohsome_elements_count(grouping = c(\"boundary\", \"tag\"), format = \"csv\") |\u003e\n\tset_filter(\"building=* and geometry:polygon\") |\u003e\n\tset_time(\"2015/2020\") |\u003e\n\tset_groupByKey(\"building:levels\") |\u003e\n\tohsome_post()\n\ndim(building_levels)\n```\n\nThe query results in a confusing data.frame with `r ncol(building_levels)` \ncolumns and `r nrow(building_levels)` rows. This happens because there is a \nbuilding count column for each combination of boundary polygon and number of \nlevels, while the two requested timestamps are in the rows. Fortunately, there \nis the \n[tidyr](https://tidyr.tidyverse.org){target=blank} \npackage to do its magic and pivot this table into a long format \nwith one value per row:\n\n```{r tidy}\nlibrary(tidyr)\n\nbuilding_levels |\u003e\n\tpivot_longer(-timestamp, names_to = c(\"id\", \"levels\"), names_sep = \"_\")\n```\n\n## How to cite this package\n\nIn order to cite this package in publications, please use the citation \ninformation provided through `citation(\"ohsome\")`.\n\n-----\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiscience%2Fohsome-r","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiscience%2Fohsome-r","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiscience%2Fohsome-r/lists"}