Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
xenatisch committed Aug 2, 2020
0 parents commit 74772ec
Show file tree
Hide file tree
Showing 21 changed files with 982 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
^LICENSE\.md$
^.*\.Rproj$
^\.Rproj\.user$
^doc$
^Meta$
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
inst/doc
doc
Meta
.Rhistory
.RData
.Rproj.user
25 changes: 25 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Package: ukcovid19
Title: What the Package Does (One Line, Title Case)
Version: 1.1.2
Authors@R:
person(
given = "Pouria",
family = "Hadjibagheri",
role = c("aut", "cre"),
email = "[email protected]",
comment = c(ORCID = "0000-0003-2739-4161")
)
Description: This is an R SDK for the COVID-19 API, as published by Public Health England on Coronavirus (COVID-19) in the UK dashboard.
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.1
Suggests:
testthat,
knitr,
rmarkdown
Imports:
httr,
jsonlite
VignetteBuilder: knitr
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2020
COPYRIGHT HOLDER: Public Health England
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MIT License

Copyright (c) 2020 Public Health England

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Generated by roxygen2: do not edit by hand

export(get_data)
export(get_head)
export(get_options)
export(last_update)
15 changes: 15 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ukcovid19 1.1.2

* Added a `NEWS.md` file to track changes to the package.

# ukcovid19 1.1.1

* Added README and documentations

# ukcovid19 1.1.0

* Added tests

# ukcovid19 1.0.0

* Initial release
308 changes: 308 additions & 0 deletions R/api.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
API_ENDPOINT <- "https://api.coronavirus.data.gov.uk/v1/data"


#' Get Request
#'
#' Generic get request. Prepares queries, retrieves the
#' data and parses the results.
#'
#' @param filters API filters.
#'
#' @param structure Structure parameter.
#'
#' @param ... Either the pagination parameter (\code{page}) or
#' the metric for \code{latestBy}.
#'
#' @return list Data for the given queries or \code{NULL}.
get_request <- function (filters, structure, ...) {

# Automatically encodes the URL and its parameters.
httr::VERB(
"GET",

# Concatenate the filters vector using a semicolon.
url = API_ENDPOINT,

# Convert the structure to JSON (ensure
# that "auto_unbox" is set to TRUE).
query = list(
filters = paste(filters, collapse = ";"),
structure = jsonlite::toJSON(
structure,
auto_unbox = TRUE,
pretty = FALSE
),
...
),

# The API server will automatically reject any
# requests that take longer than 10 seconds to
# process.
httr::timeout(10)
) -> response

# Handle errors:
if ( response$status_code >= 400 ) {

err_msg = httr::http_status(response)
stop(err_msg)

} else if ( response$status_code == 204 ) {

response <- NULL

} else {

# Convert response from binary to JSON:
json_text <- httr::content(response, "text")
response <- jsonlite::fromJSON(json_text)

}

return(response)

} # get_request


#' Get Paginated Data
#'
#' Iteratively runs the query to download all pages.
#'
#' @param filters API filters.
#'
#' @param structure Structure parameter.
#'
#' @return list Data for the given \code{filters} and \code{structure}.
get_paginated_data <- function (filters, structure) {

results <- list()
current_page <- 1

repeat {

response <- get_request(filters, structure, page = current_page)

# Must be after `get_request` is called.
if ( is.null(response) ) break;

results <- rbind(results, response$data)

# Must be after results are added.
if ( is.null(response$pagination$`next`) ) break;

current_page <- current_page + 1;

}

return(results)

} # get_paginated_data


#' Get Data
#'
#' Extracts paginated data by requesting all of the pages
#' and combining the results.
#'
#' For additional information and up-to-date details on arguments
#' and what they represent, please visit
#' the \href{API documentations}{https://coronavirus.data.gov.uk/developers-guide}.
#'
#' @param filters API filters.
#'
#' @param structure Structure parameter.
#'
#' @param latest_by Retrieves the latest value for a specific metric.
#' Must be set to a value that is defined in the
#' structure. (Default: \code{NULL})
#'
#' @return list Data for the given \code{filters} and \code{structure}.
#'
#' @export
#'
#' @examples
#' # We would like to download all cases data at `region` level.
#' # We start off by defining our `filters` argument:
#' query_filters <- c(
#' "areaType=region"
#' )
#'
#' # Next, we define the structure:
#' query_structure <- list(
#' date = "date",
#' name = "areaName",
#' code = "areaCode",
#' daily = "newCasesBySpecimenDate",
#' cumulative = "cumCasesBySpecimenDate"
#' )
#'
#' # We then pass these arguments to the `get_data` function:
#' data <- get_data(filters = query_filters, structure = query_structure)
get_data <- function (filters, structure, latest_by = NULL) {

response <- NULL

if ( is.null(latest_by) ) {

response <- get_paginated_data(filters, structure)

} else {
data <- get_request(filters, structure, latestBy = latest_by)
response <- data$data

}

return(response)

} # get_data


#' Get Options
#'
#' Provides the options by calling the \code{OPTIONS} method of the API.
#'
#' @return character API options as prettified JSON.
#'
#' @export
#'
#' @examples
#' opts <- get_options()
get_options <- function () {

httr::VERB(
"OPTIONS",

# Concatenate the filters vector using a semicolon.
url = API_ENDPOINT,

# The API server will automatically reject any
# requests that take longer than 10 seconds to
# process.
httr::timeout(10)
) -> response

# Handle errors:
if ( response$status_code >= 400 ) {
err_msg = httr::http_status(response)
stop(err_msg)
}

# Convert response from binary to JSON:
json_text <- httr::content(response, "text")
results <- jsonlite::prettify(json_text, indent = 4)

return(results)

} # get_options


#' Get Head
#'
#' Request header for the given input arguments (\code{filters},
#' \code{structure}, and \code{lastest_by}).
#'
#' @param filters API filters. See the API documentations for
#' additional information.
#'
#' @param structure Structure parameter. See the API documentations
#' for additional information.
#'
#' @return list Request headers.
#'
#' @export
#'
#' @examples
#' query_filters <- c(
#' "areaType=region"
#' )
#'
#' query_structure <- list(
#' date = "date",
#' name = "areaName",
#' code = "areaCode",
#' daily = "newCasesBySpecimenDate",
#' cumulative = "cumCasesBySpecimenDate"
#' )
#'
#' headers <- get_head(filters = query_filters, structure = query_structure)
#'
#' # We can now access header parameters. For instance, to get the
#' # timestamp for the latest update, we do as follows:
#' print(headers$`last-modified`)
get_head <- function (filters, structure) {

httr::VERB(
"HEAD",

# Concatenate the filters vector using a semicolon.
url = API_ENDPOINT,

# Convert the structure to JSON (ensure
# that "auto_unbox" is set to TRUE).
query = list(
filters = paste(filters, collapse = ";"),
structure = jsonlite::toJSON(
structure,
auto_unbox = TRUE,
pretty = FALSE
)
),

# The API server will automatically reject any
# requests that take longer than 10 seconds to
# process.
httr::timeout(10)
) -> response

# Handle errors:
if ( response$status_code >= 400 ) {
err_msg = httr::http_status(response)
stop(err_msg)
}

return(response$head)

} # get_head


#' Last Update Timestamp
#'
#' Produces the timestamp for the last update in GMT.
#'
#' @param filters API filters. See the API documentations for
#' additional information.
#'
#' @param structure Structure parameter. See the API documentations
#' for additional information.
#'
#' @return closure Timestamp of the last update.
#'
#' @export
#'
#' @examples
#' query_filters <- c(
#' "areaType=region"
#' )
#'
#' query_structure <- list(
#' date = "date",
#' name = "areaName",
#' code = "areaCode",
#' daily = "newCasesBySpecimenDate",
#' cumulative = "cumCasesBySpecimenDate"
#' )
#'
#' timestamp <- last_update(filters = query_filters, structure = query_structure)
last_update <- function (filters, structure) {

response <- get_head(filters, structure)

timestamp <- strptime(
response$`last-modified`,
format = '%a, %d %b %Y %H:%M:%S',
tz = 'GMT'
)

return(timestamp)

} # last_update
Loading

0 comments on commit 74772ec

Please sign in to comment.