Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement/geography handling #64

Merged
merged 13 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: eesyapi
Title: EES-y API
Version: 0.4.0
Version: 0.4.0.9000
Authors@R: c(
person("Rich", "Bielby", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-9070-9969")),
Expand All @@ -22,7 +22,8 @@ Imports:
magrittr,
readr,
rlang,
stringr
stringr,
tidyr
Suggests:
knitr,
rmarkdown,
Expand Down
31 changes: 0 additions & 31 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,44 +1,13 @@
# Generated by roxygen2: do not edit by hand

export(api_url)
export(api_url_pages)
export(api_url_query)
export(convert_api_filter_type)
export(example_data_raw)
export(example_geography_query)
export(example_id)
export(example_json_query)
export(get_data_catalogue)
export(get_dataset)
export(get_meta)
export(get_meta_response)
export(get_publications)
export(http_request_error)
export(parse_api_dataset)
export(parse_meta_filter_columns)
export(parse_meta_filter_item_ids)
export(parse_meta_location_ids)
export(parse_meta_time_periods)
export(parse_sqids_filters)
export(parse_sqids_indicators)
export(parse_sqids_locations)
export(parse_tojson_filter)
export(parse_tojson_filter_eq)
export(parse_tojson_filter_in)
export(parse_tojson_geographies)
export(parse_tojson_indicators)
export(parse_tojson_location)
export(parse_tojson_params)
export(parse_tojson_time_periods)
export(parse_tourl_filter_in)
export(post_dataset)
export(preview_dataset)
export(query_dataset)
export(validate_api_version)
export(validate_ees_environment)
export(validate_ees_filter_type)
export(validate_ees_id)
export(validate_page_size)
export(validate_time_periods)
export(warning_max_pages)
importFrom(data.table,":=")
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# eesyapi (development version)

# eesyapi 0.4.0

* Optimisation to parsing of JSON responses in `query_dataset()`
Expand Down
18 changes: 9 additions & 9 deletions R/api_url.R
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ api_url <- function(

# Check that if endpoint requires a data set then dataset_id is not null
if (endpoint %in% c("get-summary", "get-meta", "get-csv", "get-data", "post-data")) {
eesyapi::validate_ees_id(dataset_id, level = "dataset")
validate_ees_id(dataset_id, level = "dataset")
if (is_valid_dataset_info(dataset_id, dataset_version) == FALSE) {
stop(
paste(
Expand All @@ -109,10 +109,10 @@ api_url <- function(
# End of validation

endpoint_base <- list(
dev = "https://dev.statistics.api.education.gov.uk/api/",
test = "https://test.statistics.api.education.gov.uk/api/",
preprod = "https://pre-production.statistics.api.education.gov.uk/api/",
prod = "https://statistics.api.education.gov.uk/api/"
dev = "https://dev.statistics.api.education.gov.uk/",
test = "https://test.statistics.api.education.gov.uk/",
preprod = "https://pre-production.statistics.api.education.gov.uk/",
prod = "https://statistics.api.education.gov.uk/"
cjrace marked this conversation as resolved.
Show resolved Hide resolved
)

endpoint_base_version <- paste0(
Expand All @@ -124,15 +124,15 @@ api_url <- function(
url <- paste0(
endpoint_base_version,
"publications?",
eesyapi::api_url_pages(page_size = page_size, page = page)
api_url_pages(page_size = page_size, page = page)
)
} else if (endpoint == "get-data-catalogue") {
url <- paste0(
endpoint_base_version,
"publications/",
publication_id,
"/data-sets?",
eesyapi::api_url_pages(page_size = page_size, page = page)
api_url_pages(page_size = page_size, page = page)
)
} else {
url <- paste0(
Expand Down Expand Up @@ -173,7 +173,7 @@ api_url <- function(
}
url <- url |>
paste0(
eesyapi::api_url_query(
api_url_query(
indicators = indicators,
time_periods = time_periods,
geographic_levels = geographic_levels,
Expand All @@ -182,7 +182,7 @@ api_url <- function(
),
ifelse(
!is.null(page) & !is.null(page_size),
paste0("&", eesyapi::api_url_pages(page_size = page_size, page = page)),
paste0("&", api_url_pages(page_size = page_size, page = page)),
""
)
)
Expand Down
7 changes: 4 additions & 3 deletions R/api_url_pages.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
#' @param page Page number to return
#'
#' @return String containing pages query
#' @export
#'
#' @keywords internal
#'
#' @examples
#' api_url_pages()
#' api_url_pages(page_size = 20, page = 2)
#' eesyapi:::api_url_pages()
#' eesyapi:::api_url_pages(page_size = 20, page = 2)
api_url_pages <- function(page_size = 40, page = NULL) {
paste0(
ifelse(
Expand Down
21 changes: 11 additions & 10 deletions R/api_url_query.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
#' @param filter_items Filter items required as a string or vector of strings
#'
#' @return String containing data query string to append to GET data query URL
#' @export
#'
#' @keywords internal
#'
#' @examples
#' api_url_query(example_id("indicator"))
#' eesyapi:::api_url_query(example_id("indicator"))
api_url_query <- function(
indicators,
time_periods = NULL,
Expand All @@ -24,37 +25,37 @@ api_url_query <- function(
if (is.null(indicators)) {
stop("The keyword indicators must be supplied")
}
eesyapi::validate_ees_id(indicators, level = "indicator")
validate_ees_id(indicators, level = "indicator")
# Create the appropriate query strings for each level provided
if (!is.null(time_periods)) {
query_time_periods <- eesyapi::parse_tourl_filter_in(time_periods, "time_periods")
query_time_periods <- parse_tourl_filter_in(time_periods, "time_periods")
}
if (!is.null(geographic_levels)) {
query_geographic_levels <- eesyapi::parse_tourl_filter_in(
query_geographic_levels <- parse_tourl_filter_in(
geographic_levels,
filter_type = "geographic_levels"
)
}
if (!is.null(locations)) {
eesyapi::validate_ees_id(locations, level = "location")
query_locations <- eesyapi::parse_tourl_filter_in(locations, filter_type = "locations")
validate_ees_id(locations, level = "location")
query_locations <- parse_tourl_filter_in(locations, filter_type = "locations")
}
if (!is.null(filter_items)) {
# Note the idea below was to differentiate the logic between AND / OR based on whether
# a list of vectors is provided or a single vector. Due to limitations with GET, this
# set up doesn't make a blind bit of difference to the result, the query just performs
# an OR combination regardless.
eesyapi::validate_ees_id(filter_items, level = "filter_item")
validate_ees_id(filter_items, level = "filter_item")
if (filter_items |> typeof() == "list") {
query_filter_items <- ""
for (filter_set in filter_items) {
query_filter_items <- paste0(
query_filter_items,
eesyapi::parse_tourl_filter_in(filter_set, filter_type = "filter_items")
parse_tourl_filter_in(filter_set, filter_type = "filter_items")
)
}
} else {
query_filter_items <- eesyapi::parse_tourl_filter_in(
query_filter_items <- parse_tourl_filter_in(
filter_items,
filter_type = "filter_items"
)
Expand Down
9 changes: 5 additions & 4 deletions R/api_url_query_utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
#' "locations" or "filter_items"
#'
#' @return Query string for use in URL based API queries
#' @export
#'
#' @keywords internal
#'
#' @examples
#' parse_tourl_filter_in(c("2024|W11", "2024|W12"), filter_type = "time_periods")
#' eesyapi:::parse_tourl_filter_in(c("2024|W11", "2024|W12"), filter_type = "time_periods")
parse_tourl_filter_in <- function(
items,
filter_type) {
eesyapi::validate_ees_filter_type(filter_type)
type_string <- eesyapi::convert_api_filter_type(filter_type)
validate_ees_filter_type(filter_type)
type_string <- convert_api_filter_type(filter_type)
if (!is.null(items)) {
if (filter_type %in% c("time_period", "locations")) {
items <- gsub("\\|", "%7C", items)
Expand Down
13 changes: 7 additions & 6 deletions R/convert_api_filter_type.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
#' @inheritParams parse_tourl_filter_in
#'
#' @return String containing API friendly filter type descriptor
#' @export
#'
#' @keywords internal
#'
#' @examples
#' convert_api_filter_type("filter_items")
#' convert_api_filter_type("geographic_levels")
#' convert_api_filter_type("locations")
#' convert_api_filter_type("filter_items")
#' eesyapi:::convert_api_filter_type("filter_items")
#' eesyapi:::convert_api_filter_type("geographic_levels")
#' eesyapi:::convert_api_filter_type("locations")
#' eesyapi:::convert_api_filter_type("filter_items")
convert_api_filter_type <- function(filter_type) {
eesyapi::validate_ees_filter_type(filter_type)
validate_ees_filter_type(filter_type)
filter_type <- filter_type |>
stringr::str_replace("_item", "")
gsub("_(\\w?)", "\\U\\1", filter_type, perl = TRUE)
Expand Down
24 changes: 13 additions & 11 deletions R/examples.R
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ example_id <- function(
example_data_raw <- function(
group = "attendance",
size = 32) {
eesyapi::api_url(
api_url(
"get-data",
dataset_id = example_id(group = group),
indicators = example_id("indicator", group = group),
Expand All @@ -196,10 +196,12 @@ example_data_raw <- function(
#' @examples
#' example_json_query() |> cat()
example_json_query <- function() {
eesyapi::parse_tojson_params(
parse_tojson_params(
indicators = example_id("indicator", group = "attendance"),
time_periods = example_id("time_period", group = "attendance"),
geographies = example_id("location_codes", group = "attendance"),
geographies = todf_geographies(
example_id("location_codes", group = "attendance")
),
filter_items = example_id("filter_items_short", group = "attendance")
)
}
Expand All @@ -218,16 +220,16 @@ example_geography_query <- function(level = "nat_yorks") {
example_geography_queries <- list(
nat_yorks =
data.frame(
return_level = c("NAT", "REG"),
search_level = c("NAT", "REG"),
identifier_type = c("code", "code"),
identifier = c("E92000001", "E12000003")
geographic_level = c("NAT", "REG"),
location_level = c("NAT", "REG"),
location_id_type = c("code", "code"),
location_id = c("E92000001", "E12000003")
),
nat_yorks_yorkslas = data.frame(
return_level = c("NAT", "REG", "LA"),
search_level = c("NAT", "REG", "REG"),
identifier_type = c("code", "code", "code"),
identifier = c("E92000001", "E12000003", "E12000003")
geographic_level = c("NAT", "REG", "LA"),
location_level = c("NAT", "REG", "REG"),
location_id_type = c("code", "code", "code"),
location_id = c("E92000001", "E12000003", "E12000003")
)
)
example_geography_queries |>
Expand Down
10 changes: 5 additions & 5 deletions R/get_data_catalogue.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ get_data_catalogue <- function(
page = NULL,
verbose = FALSE) {
# Validate input parameters
eesyapi::validate_ees_id(publication_id)
eesyapi::validate_page_size(page_size)
validate_ees_id(publication_id)
validate_page_size(page_size)
# Send the GET call to the API
response <- httr::GET(
eesyapi::api_url(
api_url(
endpoint = "get-data-catalogue",
publication_id = publication_id,
ees_environment = ees_environment,
Expand All @@ -36,7 +36,7 @@ get_data_catalogue <- function(
if (response$paging$totalPages > 1) {
for (page in c(2:response$paging$totalPages)) {
response_page <- httr::GET(
eesyapi::api_url(
api_url(
endpoint = "get-data-catalogue",
publication_id = publication_id,
ees_environment = ees_environment,
Expand All @@ -54,6 +54,6 @@ get_data_catalogue <- function(
}
}
# Check that the query hasn't tried to retrieve results beyond the final page of results
response |> eesyapi::warning_max_pages()
response |> warning_max_pages()
return(response$results)
}
15 changes: 8 additions & 7 deletions R/get_dataset.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
#' @param parse Logical flag to activate parsing of the results. Default: TRUE
#'
#' @return Data frame containing query results of an API data set
#' @export
#'
#' @keywords internal
#'
#' @examples
#' get_dataset(
#' eesyapi:::get_dataset(
#' example_id(),
#' geographic_levels = c("NAT"),
#' filter_items = example_id("filter_item"),
Expand All @@ -36,7 +37,7 @@ get_dataset <- function(
page_size = 10000,
parse = TRUE,
verbose = FALSE) {
api_call <- eesyapi::api_url(
api_call <- api_url(
"get-data",
dataset_id = dataset_id,
indicators = indicators,
Expand All @@ -53,7 +54,7 @@ get_dataset <- function(
)
response <- api_call |>
httr::GET()
eesyapi::http_request_error(response)
http_request_error(response)
# Unless the user specifies a specific page of results to get, loop through all available pages.
response_json <- response |>
httr::content("text") |>
Expand All @@ -77,7 +78,7 @@ get_dataset <- function(
verbose = response_json$paging$totalPages * page_size > 100000
)
for (page in c(2:response_json$paging$totalPages)) {
response_page <- eesyapi::api_url(
response_page <- api_url(
"get-data",
dataset_id = dataset_id,
indicators = indicators,
Expand All @@ -95,7 +96,7 @@ get_dataset <- function(
httr::GET() |>
httr::content("text") |>
jsonlite::fromJSON()
response_page |> eesyapi::warning_max_pages()
response_page |> warning_max_pages()
toggle_message(
paste0("Retrieved page ", page, " of ", response_json$paging$totalPages),
verbose = verbose
Expand All @@ -110,7 +111,7 @@ get_dataset <- function(
}
if (parse) {
dfresults <- dfresults |>
eesyapi::parse_api_dataset(
parse_api_dataset(
dataset_id,
verbose = verbose,
ees_environment = ees_environment
Expand Down
Loading
Loading