R/get_theme.R

Defines functions get_theme

Documented in get_theme

#' Get Theme Data from OneMap.Sg
#'
#' @description
#' This function is a wrapper for the \href{https://www.onemap.gov.sg/docs/#retrieve-theme}{Retrieve Theme API}. It returns the data as cleaned tibbles.
#'
#' @param token User's API token. This can be retrieved using \code{\link{get_token}}
#' @param theme OneMap theme in its \code{QUERYNAME} format. A tibble of available themes can be retrieved using \code{\link{search_themes}}
#' @param extents Optional, Location Extents for search. This should be in the format "Lat1,\%20Lng1,Lat2,\%20Lng2". For more information, consult the \href{https://www.onemap.gov.sg/docs/#retrieve-theme}{API Documentation}.
#' @param return_info Default = \code{FALSE}. If \code{FALSE}, function only returns a tibble for query results. If \code{TRUE}, function returns output as a list containing a tibble for query information and a tibble for query results.
#' @param read Optional, format to read output. Valid parameters are \code{tibble}, \code{sf} and \code{rgdal}. For "sf" objects, specify \code{read = "sf"} and for "sp" objects use \code{read = "rgdal"}. Defaults to \code{tibble} if any other value is used. Please ensure the \code{sf} package is installed, else this parameter return a tibble.
#'
#' @return If no error occurs:
#' \describe{
#'   \item{query_info}{A 1 x 7 tibble containing information about the query. The variables are \code{FeatCount}, \code{Theme_Name}, \code{Category}, \code{Owner}, \code{DateTime.date}, \code{DateTime.timezone_type}, \code{DateTime.timezone}}
#'   \item{query_result}{Returned if return_info = \code{TRUE}. A tibble containing the data retrieved from the query. The columns and rows vary depending on theme and user specification, however all tibbles will contain the variables: \code{NAME}, \code{DESCRIPTION}, \code{ADDRESSPOSTALCODE}, \code{ADDRESSSTREETNAME}, \code{Lat}, \code{Lng}, \code{ICON_NAME}}
#' }
#'
#' If an error occurs, the output will be \code{NULL}, along with a warning message.
#' For non-error queries where 0 results are returned, the output will be \code{query_info}, along with a warning message.
#'
#' @export
#'
#' @examples
#' # returns a tibble of output
#' \dontrun{get_theme(token, "hotels")}
#' \dontrun{get_theme(token, "monuments",
#'     extents = "1.291789,%20103.7796402,1.3290461,%20103.8726032")}
#'
#' # returns a sf dataframe
#' \dontrun{get_theme(token, "hotels", read = "sf")}
#'
#' # returns a list of status tibble and output tibble
#' \dontrun{get_theme(token, "funeralparlours", return_info = TRUE)}
#'
#' # error: output is NULL, warning message shows status code
#' \dontrun{get_theme("invalid_token", "hotels")}
#'
#' # error: output is NULL, warning message shows error message from request
#' \dontrun{get_theme(token, "non-existent-theme")}
#'
#' # error: output is \code{query_info}, warning message query did not return any records
#' \dontrun{get_theme(token, "ura_parking_lot", "1.291789,%20103.7796402,1.3290461,%20103.8726032")}

get_theme <- function(token, theme, extents = NULL, return_info = FALSE, read = "tibble") {
  # query API
  url <- "https://developers.onemap.sg/privateapi/themesvc/retrieveTheme?"
  query <- paste(url,
                 "queryName=", theme,
                 "&token=", token,
                 sep = "")
  if (!is.null(extents)) {query <- paste(query, "&extents=", extents, sep = "")}
  response <- GET(query)
  query_results <- content(response)

  # error check: invalid request
  if (http_error(response)) {
    status <- status_code(response)
    output <- NULL
    warning(paste("The request produced a", status, "error", sep = " "))

  # else return output
  } else {

    # error check: invalid parameters
    if (names(query_results[[1]][[1]][1]) == "ErrorMessage") {
      output <- NULL
      error_msg <- query_results[[1]][[1]][[1]][[1]]
      warning(paste("The request returned the following error message:", error_msg, sep = " "))

    # error check: output length 0
    } else if (length(query_results$SrchResults) == 1) {
      output <- query_results[[1]][[1]] %>%
        unlist() %>% t() %>%
        as_tibble()
      warning("There are 0 matching records for your query.")

    } else {

      # transform output to dataframe
      output <- query_results[[1]][-1] %>%
        reduce(bind_rows) %>%
        separate(col = "LatLng", into = c("Lat", "Lng"), sep = ",")

      if (read %in% c("sf", "rgdal") & requireNamespace("sf", quietly = TRUE)) {
        output <- sf::st_as_sf(output, coords = c("Lng", "Lat"))

        if (read == "rgdal") {
          output <- sf::as_Spatial(output)
        }

      }

      # transform output to a list containing query info and query results if user wants info
      if (return_info) {

        # store query info
        query_info <- query_results[[1]][[1]] %>%
          unlist() %>% t() %>%
          as_tibble()

        # reformat output
        output <- list(query_info = query_info, query_results = output)
      }
    }
  }

  output

}

Try the onemapsgapi package in your browser

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

onemapsgapi documentation built on Nov. 29, 2022, 9:06 a.m.