R/osm_get_changesets.R

Defines functions osm_get_changesets

Documented in osm_get_changesets

# Vectorized version of osm_read_changeset

#' Get changesets
#'
#' Returns the changesets with the given `changeset_id`.
#'
#' @param changeset_id A vector with ids of changesets to retrieve represented by a numeric or a character values.
#' @param include_discussion Indicates whether the result should contain the changeset discussion or not.
#' @param format Format of the output. Can be `"R"` (default), `"sf"`, `"xml"`, or `"json"`.
#' @param tags_in_columns If `FALSE` (default), the tags of the changesets are saved in a single list column `tags`
#'   containing a `data.frame` for each changeset with the keys and values. If `TRUE`, add a column for each key.
#'   Ignored if `format != "R"`.
#'
#' @details
#' * The `uid` might not be available for changesets auto generated by the API v0.5 to API v0.6 transition
#' * The bounding box attributes will be missing for an empty changeset.
#' * The changeset bounding box is a rectangle that contains the bounding boxes of all objects changed in this
#'   changeset. It is not necessarily the smallest possible rectangle that does so.
#' * This API call only returns information about the changeset itself but not the actual changes made to elements in
#'   this changeset. To access this information use [osm_download_changeset()].
#'
#' @return
#' If `format = "R"`, returns a data frame with one OSM changeset per row. If `format = "sf"`, returns a `sf` object
#' from \pkg{sf}.
#'
#' ## `format = "xml"`
#' Returns a [xml2::xml_document-class] with the following format:
#' ``` xml
#' <osm version="0.6" generator="CGImap 0.9.3 (987909 spike-08.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
#'   <changeset id="10" created_at="2008-11-08T19:07:39+01:00" open="true" user="fred" uid="123" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101" comments_count="3" changes_count="10">
#'     <tag k="created_by" v="JOSM 1.61"/>
#'     <tag k="comment" v="Just adding some streetnames"/>
#'     ...
#'     <discussion>
#'       <comment id="1234" date="2015-01-01T18:56:48Z" uid="1841" user="metaodi">
#'         <text>Did you verify those street names?</text>
#'       </comment>
#'       <comment id="5678" date="2015-01-01T18:58:03Z" uid="123" user="fred">
#'         <text>sure!</text>
#'       </comment>
#'       ...
#'     </discussion>
#'   </changeset>
#'   <changeset>
#'     ...
#'   </changeset>
#' </osm>
#' ```
#'
#' ## `format = "json"`
#' *Please note that the JSON format has changed on August 25, 2024 with the release of openstreetmap-cgimap 2.0.0, to*
#' *align it with the existing Rails format.*
#'
#' Returns a list with the following json structure:
#' ``` json
#' {
#'   "version": "0.6",
#'   "generator": "openstreetmap-cgimap 2.0.0 (4003517 spike-08.openstreetmap.org)",
#'   "copyright": "OpenStreetMap and contributors",
#'   "attribution": "http://www.openstreetmap.org/copyright",
#'   "license": "http://opendatacommons.org/licenses/odbl/1-0/",
#'   "changeset": [
#'     {
#'       "id": 10,
#'       "created_at": "2005-05-01T16:09:37Z",
#'       "open": false,
#'       "comments_count": 1,
#'       "changes_count": 10,
#'       "closed_at": "2005-05-01T17:16:44Z",
#'       "min_lat": 59.9513092,
#'       "min_lon": 10.7719727,
#'       "max_lat": 59.9561501,
#'       "max_lon": 10.7994537,
#'       "uid": 24,
#'       "user": "Petter Reinholdtsen",
#'       "comments": [
#'         {
#'           "id": 836447,
#'           "visible": true,
#'           "date": "2022-03-22T20:58:30Z",
#'           "uid": 15079200,
#'           "user": "Ethan White of Cheriton",
#'           "text": "wow no one have said anything here 3/22/2022\n"
#'         }
#'       ]
#'     },
#'     ...
#'   ]
#' }
#' ```
#'
#' @family get changesets' functions
#' @export
#'
#' @examples
#' chaset <- osm_get_changesets(changeset_id = 137595351, include_discussion = TRUE)
#' chaset
#' chaset$discussion
osm_get_changesets <- function(changeset_id, include_discussion = FALSE,
                               format = c("R", "sf", "xml", "json"), tags_in_columns = FALSE) {
  format <- match.arg(format)
  .format <- if (format == "sf") "R" else format
  if (format == "sf" && !requireNamespace("sf", quietly = TRUE)) {
    stop("Missing `sf` package. Install with:\n\tinstall.package(\"sf\")")
  }

  if (length(changeset_id) == 1) {
    out <- osm_read_changeset(
      changeset_id = changeset_id, include_discussion = include_discussion,
      format = .format, tags_in_columns = tags_in_columns
    )
  } else {
    outL <- lapply(changeset_id, function(id) {
      osm_read_changeset(changeset_id = id, include_discussion = include_discussion, format = .format)
    })

    if (.format == "R") {
      out <- do.call(rbind, outL)
      if (tags_in_columns) {
        out <- tags_list2wide(out)
      }
    } else if (.format == "xml") {
      out <- xml2::xml_new_root(outL[[1]])
      for (i in seq_along(outL[-1]) + 1) {
        lapply(xml2::xml_children(outL[[i]]), function(node) {
          xml2::xml_add_child(out, node)
        })
      }
    } else if (.format == "json") {
      out <- outL[[1]]
      if (length(outL) > 1) {
        out$elements <- do.call(c, c(list(out$elements), lapply(outL[-1], function(x) x$elements)))
      }
    }
  }

  if (format == "sf") {
    out <- sf::st_as_sf(out)
  }

  return(out)
}

Try the osmapiR package in your browser

Any scripts or data that you put into this service are public.

osmapiR documentation built on April 15, 2025, 9:06 a.m.