diff --git a/.lintr b/.lintr index fb125ea..3d4eb22 100644 --- a/.lintr +++ b/.lintr @@ -1,2 +1,2 @@ linters: linters_with_defaults() # see vignette("lintr") -encoding: "UTF-8" \ No newline at end of file +encoding: "UTF-8" diff --git a/NAMESPACE b/NAMESPACE index 98947ce..0785192 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,16 @@ # Generated by roxygen2: do not edit by hand +export(uis_get) +export(uis_get_entities) +export(uis_get_versions) +export(uis_get_versions_default) import(cli) import(httr2) import(jsonlite) import(tibble) +importFrom(dplyr,filter) +importFrom(dplyr,mutate) +importFrom(dplyr,rename) +importFrom(dplyr,select) +importFrom(tidyr,nest) +importFrom(tidyr,unnest) diff --git a/R/perform_request.R b/R/perform_request.R index ab855c1..c83da99 100644 --- a/R/perform_request.R +++ b/R/perform_request.R @@ -4,7 +4,8 @@ perform_request <- function( resource, entities = NULL, indicators = NULL, - time = NULL, + start_year = NULL, + end_year = NULL, version = NULL, disaggregations = NULL, glossary_terms = NULL @@ -16,11 +17,14 @@ perform_request <- function( req <- request(base_url) |> req_url_path_append(resource) |> req_url_query( - entities = entities, - + geoUnit = entities, + indicator = indicators, + start = start_year, + end = end_year, version = version, disaggregations = disaggregations, - glossary_terms = glossary_terms + glossary_terms = glossary_terms, + .multi = "explode" ) tryCatch( @@ -41,4 +45,6 @@ perform_request <- function( ) } ) + + resp } diff --git a/R/uis_get.R b/R/uis_get.R index cebf565..7c38833 100644 --- a/R/uis_get.R +++ b/R/uis_get.R @@ -1,3 +1,50 @@ +#' Get data from the UIS API +#' +#' @description +#' Retrieves data from the UNESCO Institute for Statistics (UIS) API for +#' specified entities, indicators, and time periods. +#' +#' @param entities Character vector. The entity IDs (geoUnits) to retrieve data +#' for. Must provide either this parameter or `indicators` or both. +#' @param indicators Character vector. The indicator IDs to retrieve data for. +#' Must provide either this parameter or `entities` or both. +#' @param start_year Numeric or character. The starting year for the data +#' retrieval period. If NULL, no start year constraint is applied. +#' @param end_year Numeric or character. The ending year for the data retrieval +#' period. If NULL, no end year constraint is applied. +#' @param version Character. The API version to use. If NULL, the default +#' version is used. +#' +#' @return A data frame with the following columns: +#' \item{entity_id}{Character. The ID of the entity (geoUnit).} +#' \item{indicator_id}{Character. The ID of the indicator.} +#' \item{year}{Numeric. The year of the observation.} +#' \item{value}{Numeric. The value of the indicator for the given entity and +#' year.} +#' +#' @examplesIf curl::has_internet() +#' \donttest{ +#' # Get a single indicator for all countries +#' literacy_data <- uis_get( +#' indicators = "200101", +#' start_year = 2015, +#' end_year = 2020 +#' ) +#' +#' # Get multiple indicators for a single country +#' uis_get( +#' entities = "BRA", +#' indicators = c("GER.1", "NER.1", "CR.1"), +#' start_year = 2010, +#' end_year = 2020 +#' ) +#' } +#' +#' @seealso +#' \link{uis_get_entities} for retrieving available geographical entities and +#' \link{uis_get_versions} for retrieving available API versions +#' +#' @export uis_get <- function( entities = NULL, indicators = NULL, @@ -5,24 +52,80 @@ uis_get <- function( end_year = NULL, version = NULL ) { - # TODO: at least entities or indicators must be given + if (is.null(entities) && is.null(indicators)) { + cli::cli_abort( + c( + "!" = "At least {.arg entities} or {.arg indicators} must be provided." + ) + ) + } - # TODO: add parameter validation + validate_character_vector(indicators, "indicators") + validate_character_vector(entities, "entities") + validate_year(start_year, "end_year") + validate_year(end_year, "end_year") + validate_version(version) - # TODO: add support for parameters - resp <- perform_request("data/indicators") + resp <- perform_request( + "data/indicators", + entities = entities, + indicators = indicators, + start_year = start_year, + end_year = end_year, + version = version + ) data_raw <- resp |> resp_body_json(simplifyVector = TRUE) - data <- data_raw$records |> - as_tibble() |> - dplyr::select( - entity_id = geoUnit, - indicator_id = indicatorId, - year, - value + records <- data_raw$records + + print(length(records)) + if (length(records) == 0) { + cli::cli_inform( + c("i" = "No records found for this query.") ) + return(invisible(NULL)) + } else { + data <- records |> + as_tibble() |> + dplyr::select( + "entity_id" = "geoUnit", + "indicator_id" = "indicatorId", + "year", + "value" + ) + return(data) + } +} + +#' @noRd +#' @keywords internal +validate_character_vector <- function(arg, arg_name) { + if (!is.null(arg)) { + if (!is.character(arg) || any(is.na(arg))) { + cli::cli_abort( + c( + "!" = paste( + "{.arg {arg_name}} must be a character vector and cannot contain ", + "NA values." + ) + ) + ) + } + } +} - data +#' @noRd +#' @keywords internal +validate_year <- function(year, arg_name) { + if (!is.null(year)) { + if (!is.numeric(year)) { + cli::cli_abort( + c( + "!" = paste("{.arg {arg_name}} must be an integer.") + ) + ) + } + } } diff --git a/R/uis_get_entities.R b/R/uis_get_entities.R index d777d7c..194be89 100644 --- a/R/uis_get_entities.R +++ b/R/uis_get_entities.R @@ -1,20 +1,51 @@ +#' Get geographical entities from UIS API +#' +#' @description +#' Retrieves information about geographical entities (countries, regions, etc.) +#' available in the UNESCO Institute for Statistics (UIS) API. +#' +#' @param version Character. The API version to use. If NULL (default), the +#' API's default version will be used. +#' +#' @return A data frame with information about geographical entities: +#' \item{entity_id}{Character. The unique identifier for the entity.} +#' \item{entity_name}{Character. The name of the geographical entity.} +#' \item{entity_typ}{Character. The type of entity (e.g., country, region).} +#' \item{region_group}{Character or list. Information about the region +#' grouping.} +#' +#' @examples +#' \donttest{ +#' uis_get_entities() +#' +#' # Download entities for a specific version +#' uis_get_entities("20250225-2ae60fad") +#' } +#' +#' @seealso +#' \link{uis_get_versions} for retrieving available API versions and +#' \link{uis_get_versions_default} for getting the default API version +#' +#' @export uis_get_entities <- function( version = NULL ) { - # TODO: add parameter validation + validate_version(version) - # TODO: add support for parameters - resp <- perform_request("definitions/geounits") + resp <- perform_request( + "definitions/geounits", + version = version + ) entities_raw <- resp_body_json(resp) |> dplyr::bind_rows() entities <- entities_raw |> dplyr::rename( - entity_id = id, - entity_name = name, - entity_typ = type, - region_group = regionGroup + "entity_id" = "id", + "entity_name" = "name", + "entity_typ" = "type", + "region_group" = "regionGroup" ) entities <- convert_to_snake_case(entities) diff --git a/R/uis_get_indicators.R b/R/uis_get_indicators.R index e4e8000..30c663a 100644 --- a/R/uis_get_indicators.R +++ b/R/uis_get_indicators.R @@ -3,20 +3,23 @@ uis_get_indicators <- function( disaggregations = NULL, glossary_terms = NULL ) { - # TODO: add parameter validation + validate_version(version) # TODO: add support for parameters - resp <- perform_request("definitions/indicators") + resp <- perform_request( + "definitions/indicators", + version = version + ) indicators_raw <- resp_body_json(resp, simplifyVector = TRUE) |> as_tibble() # TODO: rename columns and nest them again afterwards with new names indicators <- indicators_raw |> - tidyr::unnest(dataAvailability) |> - tidyr::unnest(timeLine) |> - tidyr::unnest(geoUnits) |> - tidyr::unnest(types) + tidyr::unnest("dataAvailability") |> + tidyr::unnest("timeLine") |> + tidyr::unnest("geoUnits") |> + tidyr::unnest("types") indicators <- convert_to_snake_case(indicators) diff --git a/R/uis_get_versions.R b/R/uis_get_versions.R index dceb822..5698307 100644 --- a/R/uis_get_versions.R +++ b/R/uis_get_versions.R @@ -1,3 +1,31 @@ +#' Get available UIS API versions +#' +#' @description +#' Retrieves information about the available versions of the UNESCO Institute +#' for Statistics (UIS) API, including version IDs, descriptions, and theme +#' data. +#' +#' @return A data frame with the following columns: +#' \item{id}{Character. The version identifier.} +#' \item{code}{Character. The version code.} +#' \item{description}{Character. The description of the version.} +#' \item{release_date}{Character. The date when the version was released.} +#' \item{theme}{List column. Each element is a nested data frame containing +#' information about themes available in the version, with columns: +#' \itemize{ +#' \item{theme_id}{Character. The theme identifier.} +#' \item{theme_last_update}{Character. The date when the theme was last +#' updated.} +#' \item{theme_description}{Character. The description of the theme.} +#' } +#' } +#' +#' @examplesIf curl::has_internet() +#' \donttest{ +#' uis_get_versions() +#' } +#' +#' @export uis_get_versions <- function() { resp <- perform_request("versions") @@ -5,17 +33,72 @@ uis_get_versions <- function() { as_tibble() versions <- versions_raw |> - dplyr::rename(versionDescription = description) |> - tidyr::unnest(themeDataStatus) |> + dplyr::rename("versionDescription" = "description") |> + tidyr::unnest("themeDataStatus") |> dplyr::rename( - themeId = theme, - themeLastUpdate = lastUpdate, - themeDescription = description + "themeId" = "theme", + "themeLastUpdate" = "lastUpdate", + "themeDescription" = "description" ) |> - dplyr::rename(description = versionDescription) + dplyr::rename( + "description" = "versionDescription" + ) versions <- convert_to_snake_case(versions) |> - tidyr::nest(theme = c(theme_id, theme_last_update, theme_description)) + tidyr::nest( + theme = c("theme_id", "theme_last_update", "theme_description") + ) versions } + +#' @rdname uis_get_versions +#' @export +uis_get_versions_default <- function() { + resp <- perform_request("versions/default") + + versions_default_raw <- resp_body_json(resp, simplifyVector = TRUE) |> + as_tibble() + + versions_default <- versions_default_raw |> + dplyr::rename("versionDescription" = "description") |> + tidyr::unnest("themeDataStatus") |> + dplyr::rename( + "themeId" = "theme", + "themeLastUpdate" = "lastUpdate", + "themeDescription" = "description" + ) |> + dplyr::rename( + "description" = "versionDescription" + ) + + versions_default <- convert_to_snake_case(versions_default) |> + tidyr::nest( + theme = c("theme_id", "theme_last_update", "theme_description") + ) + + versions_default +} + +#' @keywords internal +#' @noRd +validate_version <- function(version) { + if (!is.null(version)) { + if (!is.character(version)) { + cli::cli_abort( + c( + "!" = "{.arg version} must be a character." + ) + ) + } + version_length <- nchar(version) + if (version_length != 17) { + cli::cli_abort( + c( + "!" = "{.arg version} must have length 17.", + "x" = "You've supplied {version_length}." + ) + ) + } + } +} diff --git a/R/uis_get_versions_default.R b/R/uis_get_versions_default.R deleted file mode 100644 index ce8277b..0000000 --- a/R/uis_get_versions_default.R +++ /dev/null @@ -1,21 +0,0 @@ -uis_get_versions_default <- function() { - resp <- perform_request("versions/default") - - versions_default_raw <- resp_body_json(resp, simplifyVector = TRUE) |> - as_tibble() - - versions_default <- versions_default_raw |> - dplyr::rename(versionDescription = description) |> - tidyr::unnest(themeDataStatus) |> - dplyr::rename( - themeId = theme, - themeLastUpdate = lastUpdate, - themeDescription = description - ) |> - dplyr::rename(description = versionDescription) - - versions_default <- convert_to_snake_case(versions_default) |> - tidyr::nest(theme = c(theme_id, theme_last_update, theme_description)) - - versions_default -} diff --git a/man/uis_get.Rd b/man/uis_get.Rd new file mode 100644 index 0000000..d3afe4e --- /dev/null +++ b/man/uis_get.Rd @@ -0,0 +1,66 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/uis_get.R +\name{uis_get} +\alias{uis_get} +\title{Get data from the UIS API} +\usage{ +uis_get( + entities = NULL, + indicators = NULL, + start_year = NULL, + end_year = NULL, + version = NULL +) +} +\arguments{ +\item{entities}{Character vector. The entity IDs (geoUnits) to retrieve data +for. Must provide either this parameter or \code{indicators} or both.} + +\item{indicators}{Character vector. The indicator IDs to retrieve data for. +Must provide either this parameter or \code{entities} or both.} + +\item{start_year}{Numeric or character. The starting year for the data +retrieval period. If NULL, no start year constraint is applied.} + +\item{end_year}{Numeric or character. The ending year for the data retrieval +period. If NULL, no end year constraint is applied.} + +\item{version}{Character. The API version to use. If NULL, the default +version is used.} +} +\value{ +A data frame with the following columns: +\item{entity_id}{Character. The ID of the entity (geoUnit).} +\item{indicator_id}{Character. The ID of the indicator.} +\item{year}{Numeric. The year of the observation.} +\item{value}{Numeric. The value of the indicator for the given entity and +year.} +} +\description{ +Retrieves data from the UNESCO Institute for Statistics (UIS) API for +specified entities, indicators, and time periods. +} +\examples{ +\dontshow{if (curl::has_internet()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +# Get a single indicator for all countries +literacy_data <- uis_get( + indicators = "200101", + start_year = 2015, + end_year = 2020 +) + +# Get multiple indicators for a single country +uis_get( + entities = "BRA", + indicators = c("GER.1", "NER.1", "CR.1"), + start_year = 2010, + end_year = 2020 +) +} +\dontshow{\}) # examplesIf} +} +\seealso{ +\link{uis_get_entities} for retrieving available geographical entities and +\link{uis_get_versions} for retrieving available API versions +} diff --git a/man/uis_get_entities.Rd b/man/uis_get_entities.Rd new file mode 100644 index 0000000..98973a2 --- /dev/null +++ b/man/uis_get_entities.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/uis_get_entities.R +\name{uis_get_entities} +\alias{uis_get_entities} +\title{Get geographical entities from UIS API} +\usage{ +uis_get_entities(version = NULL) +} +\arguments{ +\item{version}{Character. The API version to use. If NULL (default), the +API's default version will be used.} +} +\value{ +A data frame with information about geographical entities: +\item{entity_id}{Character. The unique identifier for the entity.} +\item{entity_name}{Character. The name of the geographical entity.} +\item{entity_typ}{Character. The type of entity (e.g., country, region).} +\item{region_group}{Character or list. Information about the region +grouping.} +} +\description{ +Retrieves information about geographical entities (countries, regions, etc.) +available in the UNESCO Institute for Statistics (UIS) API. +} +\examples{ +\donttest{ +uis_get_entities() + +# Download entities for a specific version +uis_get_entities("20250225-2ae60fad") +} + +} +\seealso{ +\link{uis_get_versions} for retrieving available API versions and +\link{uis_get_versions_default} for getting the default API version +} diff --git a/man/uis_get_versions.Rd b/man/uis_get_versions.Rd new file mode 100644 index 0000000..209695c --- /dev/null +++ b/man/uis_get_versions.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/uis_get_versions.R +\name{uis_get_versions} +\alias{uis_get_versions} +\alias{uis_get_versions_default} +\title{Get available UIS API versions} +\usage{ +uis_get_versions() + +uis_get_versions_default() +} +\value{ +A data frame with the following columns: +\item{id}{Character. The version identifier.} +\item{code}{Character. The version code.} +\item{description}{Character. The description of the version.} +\item{release_date}{Character. The date when the version was released.} +\item{theme}{List column. Each element is a nested data frame containing +information about themes available in the version, with columns: +\itemize{ +\item{theme_id}{Character. The theme identifier.} +\item{theme_last_update}{Character. The date when the theme was last +updated.} +\item{theme_description}{Character. The description of the theme.} +} +} +} +\description{ +Retrieves information about the available versions of the UNESCO Institute +for Statistics (UIS) API, including version IDs, descriptions, and theme +data. +} +\examples{ +\dontshow{if (curl::has_internet()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +uis_get_versions() +} +\dontshow{\}) # examplesIf} +} diff --git a/man/uisapi-package.Rd b/man/uisapi-package.Rd index d830000..6fc7926 100644 --- a/man/uisapi-package.Rd +++ b/man/uisapi-package.Rd @@ -18,7 +18,7 @@ Useful links: } \author{ -\strong{Maintainer}: Christoph Scheuch \email{christophh@tidy-intelligence.com} (\href{https://orcid.org/0009-0004-0423-6819}{ORCID}) [copyright holder] +\strong{Maintainer}: Christoph Scheuch \email{christoph@tidy-intelligence.com} (\href{https://orcid.org/0009-0004-0423-6819}{ORCID}) [copyright holder] } \keyword{internal}