# Country R6 class: ----
#' R6 Class representing a country.
#'
#' @description
#' Objects of class Country_R6 provide a chance for the user to call any
#' of the supported APIs for their country of interest. Each instance of
#' class Country_R6 is country-specific, and it follows that the main
#' requirement to create or instantiate a copy of this class is the
#' country's name (see the \code{new} method for an example). While some
#' countries might have more than one name, the Country_R6 class does not
#' have any control over the name accepted by the APIs. Also, it is
#' noteworthy to highlight that the response of the API might differ based
#' on the country name used. The \code{new} method informs the user about
#' the availability of data for their respective country (or country
#' name); therefore, the user can experiment with different names for
#' their country of interest and gage which of the names is globally
#' accepted by the APIs.
#' @format An [R6::R6Class] object.
#' @name Country_R6
NULL
#'
#' @rdname Country_R6
#' @export
Country_R6 <- R6::R6Class(
# Object name:
classname = "Country_R6",
# Public elements:
public = list(
#' @field country_code the iso2 and iso3 codes for the country of
#' interest
country_code = NULL,
#' @field data_status bolean for whether data exists in a specific API
data_status = NULL,
#' @field dhs_survey_years years of DHS surveys for the country
dhs_survey_years = NULL,
#' @field dhs_survey_ids the labels (ids) of DHS surveys for the
#' country
dhs_survey_ids = NULL,
#' @field dhs_indicators the names of indicators available from the
#' country's DHS surveys
dhs_indicators = NULL,
#' @field dhs_data all country DHS data available via the dhs API
dhs_data = NULL,
#' @field gho_indicators list of all GHO API indicators
gho_indicators = NULL,
#' @field gho_data country GHO API indicator data
gho_data = NULL,
#' @field wb_auxiliaries all World Bank auxiliary data
wb_auxiliaries = NULL,
#' @field wb_indicators all World Bank indicators available via the
#' World Bank API
wb_indicators = NULL,
#' @field wb_data the indicator specific data retrieved from via the
#' World Bank API
wb_data = NULL,
#' @field health_facilities_data all country-specific health
#' facilities information fetched from the healthsites.io API
health_facilities_data = NULL,
#' @field health_facilities_stats country-specifc health facilities'
#' numbers by type
health_facilities_stats = NULL,
#' @field health_facilities_map a map showing country-specific health
#' facilities'
health_facilities_map = NULL,
#' @description
#' Initialisation method (triggered when a new object is created).
#' This function checks whether data is available, allowing users to
#' quickly see whether or not it is possible to call the API
#'
#' @param country_name The name of the country for which the APIs
#' will be queried.
#' @param hs_API_key Healthsites API key/token. The API seems to work
#' with any string passed to it. This behaviour might change in the
#' future and this method is written to handle calls using valid keys
#' @param shiny_ Logical, if TRUE, function will suppress some
#' messages; otherwise, the function will print useful information to
#' the console
#' @return A new `Country_R6` object.
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' }
initialize = function(country_name, hs_API_key = NULL,
shiny_ = FALSE) {
private$country_name <- stringr::str_to_title(country_name)
# Override " " if a HS API key was supplied:
if(!is.null(hs_API_key))
private$hs_API_key <- hs_API_key
# Check for data via the GHO API:
## Grab country id for GHO queries:
self$country_code['GHO'] <-
tryCatch({
tmp <- private$gho_api_query(
.query_ = "countryNames",
.query_args_ = NULL,
.country_code_ = NULL) %>%
private$gho_extract_data() %>%
dplyr::filter(Title %in% private$country_name) %>%
dplyr::pull(Code)
# filtering returns no error for countries with no DHS data:
tmp <- if(length(tmp) > 0) tmp else {
cat("\n",
glue::glue("\rGHO: {private$country_name} data is currently unavailable."))
NA_character_
}
}, error = function(e){
NA_character_
})
## Set data status to TRUE if code/name exists via API:
self$data_status['GHO'] <-
if(!is.na(self$country_code['GHO'])) TRUE else FALSE
# Check if country data is available via the DHS API:
## Grab country id for DHS queries:
self$country_code['DHS'] <-
tryCatch({
tmp <- private$dhs_api_query(
.query_ = 'countryNames',
.country_code_ = NULL) %>%
private$dhs_extract_data() %>%
dplyr::filter(CountryName %in% private$country_name) %>%
dplyr::pull(DHS_CountryCode)
# filtering returns no error for countries with no DHS data:
tmp <- if(length(tmp) > 0) tmp else {
cat("\n",
glue::glue("\rDHS: {private$country_name} data is currently unavailable."))
NA_character_
}
}, error = function(e){
NA_character_
})
## Set data status to TRUE if code/name exists via API:
self$data_status['DHS'] <-
if(!is.na(self$country_code['DHS'])) TRUE else FALSE
# Check for data via the WB API:
## Grab country id for WB queries:
self$wb_auxiliaries <- private$wb_codes_indicators()
self$country_code['WB'] <-
tryCatch({
tmp <- self$wb_auxiliaries$iso_codes %>%
dplyr::filter(country %in% private$country_name) %>%
dplyr::pull(iso2c)
# filtering returns no error for countries with no DHS data:
tmp <- if(length(tmp) > 0) tmp else {
cat("\n",
glue::glue("\rWB: {private$country_name} data is currently unavailable."))
NA_character_
}
}, error = function(e){
NA_character_
})
## Set data status to TRUE if code/name exists via API:
self$data_status['WB'] <-
if(!is.na(self$country_code['WB'])) TRUE else FALSE
# Check if country data is available via in the HS API:
## Grab country name from HS response:
self$country_code['HS'] <-
tryCatch({
tmp <- private$hs_api_query(
.query_ = 'country',
.country_name_ = private$country_name,
.API_key_ = private$hs_API_key)$
outputs %>%
private$hs_extract_values(
.data_ = .,
.levels_ = 'label',
.func_ = 'map_chr',
.default_ = NA_character_)
# filtering returns no error for countries with no DHS data:
tmp <- if(length(tmp) > 0) tmp else {
cat("\n",
glue::glue("\rHS: {private$country_name} data is currently unavailable."),
"\n")
NA_character_
}
}, error = function(e){
NA_character_
})
## Set data status to TRUE if code/name exists via API:
self$data_status['HS'] <-
if(!is.na(self$country_code['HS'])) TRUE else FALSE
# Inform user (not shiny) which APIs data are available:
if(!isTRUE(shiny_)) print(self$data_status)
},
#' @description
#' The initial query of user selected APIs
#'
#' @param API_name_ A string or vector of strings with the
#' abbreviation of the API to start querying. Accepted values are
#' Global Health Observatory (GHO), Demographic and Health Surveys
#' (DHS), World bank (WB), and Healthsities (HS).
#'
#' @return Nothing back to the user, but populates several internal
#' fields based on the \code{API_name_} passed to the function. These
#' could include GHO (for example gho_indicators), DHS (for example
#' dhs_indicators), WB (for example wb_indicators) and HS (for example
#' health_facilities_data) objects.
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Initiate API queries for HS, DHS, WB, and GHO:
#' Kenya$
#' initiate_APIs(
#' API_name_ = c("HS", "DHS", "WB", "GHO")
#' )
#' }
initiate_APIs = function(API_name_ = c("HS", "DHS", "WB", "GHO")) {
API_name_ <- stringr::str_to_upper(API_name_)
supported_APIs <- c("HS", "GHO", "WB", "DHS")
# Inform the user if requested API is not supported:
if(!all(API_name_ %in% supported_APIs))
print(
paste0(API_name_[!API_name_ %in% supported_APIs],
" is unknown or currently unsupported.
The package currently supports:
- Global Health Observatory (GHO)
- Demographic and Health Surveys (DHS)
- World bank (WB), and
- Healthsities (HS) API"))
# Initiate Global Health Observatory (GHO) API query:
if(any("GHO" %in% API_name_)) {
if(isTRUE(self$data_status["GHO"])) {
## Grab GHO indicators:
self$initiate_GHO_API()
}
}
# Initiate Demographic and Health Surveys (DHS) API query:
if(any("DHS" %in% API_name_)) {
if(isTRUE(self$data_status["DHS"])) {
## Fetch all DHS data for the country of interest:
self$initiate_DHS_API()
}
}
# Initiate World bank (WB) API query:
if(any("WB" %in% API_name_)) {
if(isTRUE(self$data_status["WB"])) {
## Grab WB indicators:
self$initiate_WB_API()
}
}
# Initiate Healthsites (HS) API query:
if(any("HS" %in% API_name_)) {
if(isTRUE(self$data_status["HS"])) {
### Fetch all Healthsites data for the country of interest:
self$initiate_HS_API()
}
}
invisible(self)
},
#' @description
#' Query Global Health Observatory (GHO) API
#'
#' @return Nothing to the user, but populates several fields in the
#' object calling the method
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Initiate API:
#' Kenya$
#' initiate_GHO_API()
#' }
initiate_GHO_API = function() {
# Initiate Global Health Observatory (GHO) API query:
if(isTRUE(self$data_status["GHO"]) &
is.null(self$gho_indicators)) {
## Grab GHO indicators:
self$gho_indicators <- private$gho_api_query(
.query_ = "indicatorsList",
.query_args_ = NULL,
.country_code_ = NULL
) %>%
private$gho_extract_data()
cat("\n",
glue::glue("\rGHO: Finished fetching GHO indicators."))
}
invisible(self)
},
#' @description
#' Query Demographic and Health Surveys (DHS) API
#'
#' @return Nothing to the user, but populates several fields in the
#' object calling the method
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Initiate API:
#' Kenya$
#' initiate_DHS_API()
#' }
initiate_DHS_API = function() {
# Initiate Demographic and Health Surveys (DHS) API query:
if(isTRUE(self$data_status["DHS"]) &
is.null(self$dhs_indicators)) {
## Fetch all DHS data for the country interest:
self$dhs_data <- private$dhs_api_query(
.query_ = "countryData",
.country_code_ = self$country_code["DHS"]) %>%
private$dhs_extract_data()
## Save survey years and ids for filtering purposes:
self$dhs_survey_years <- self$dhs_data %>%
dplyr::select(SurveyYear) %>%
dplyr::distinct()
self$dhs_survey_ids <- self$dhs_data %>%
dplyr::select(SurveyId) %>%
dplyr::distinct()
## Save available indicators for filtering purposes:
self$dhs_indicators <- self$dhs_data %>%
dplyr::select(IndicatorId, Indicator) %>%
dplyr::distinct()
}
invisible(self)
},
#' @description
#' Query World bank (WB) API
#'
#' @return Nothing to the user, but populates several fields in the
#' object calling the method
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Initiate API:
#' Kenya$
#' initiate_WB_API()
#' }
initiate_WB_API = function() {
# Initiate World bank (WB) API query:
if(isTRUE(self$data_status["WB"]) &
is.null(self$wb_indicators)) {
## Grab WB indicators:
self$wb_indicators <- self$wb_auxiliaries$indicator_labels
cat("\n",
glue::glue("\rWB: Finished fetching WB indicators."))
}
invisible(self)
},
#' @description
#' Query Healthsities (HS) API
#'
#' @return Nothing to the user, but populates several fields in the
#' object calling the method
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Initiate API:
#' Kenya$
#' initiate_HS_API()
#' }
initiate_HS_API = function() {
# Initiate Healthsites (HS) API query:
if(isTRUE(self$data_status["HS"]) &
is.null(self$health_facilities_data)) {
## Query Healthsites API:
# Set data:
self$health_facilities_data <- tryCatch(
expr = {
tmp <- private$hs_facilities_query() %>%
private$hs_extract_dataset()
tmp <- if(length(tmp) > 0) {
tmp
} else {
cat("\n",
glue::glue("\rHS: No data available for {private$country_name}.")
)
dplyr::tibble(
" " = glue::glue("No data available for {private$country_name}.")
)
}
}, error = function(e) {
cat("\n",
glue::glue("\rHS: No data available for {private$country_name}.")
)
dplyr::tibble(
" " = glue::glue("No data available for {private$country_name}.")
)
}
)
# Set stats:
self$health_facilities_stats <- tryCatch(
expr = {
tmp <- self$health_facilities_data %>%
dplyr::count(attributes.amenity)
tmp <- if(length(tmp) > 0) {
tmp
} else {
dplyr::tibble(
" " = glue::glue("No data available for {private$country_name}.")
)
}
}, error = function(e) {
dplyr::tibble(
" " = glue::glue("No data available for {private$country_name}.")
)
}
)
# Set map:
self$health_facilities_map <-
tryCatch(
expr = {
tmp <- private$hs_map_facilities(
.data_ = self$health_facilities_data)
tmp <- if(length(tmp) > 0) tmp else NULL
}, error = function(e) {
NULL
}
)
}
invisible(self)
},
#' @description
#' Get data from a specific socio-economic data from the World
#' Bank
#'
#' @param indicator_label WB indicator name or indicator label.
#' @param date_from Range of data required, start date
#' @param date_to Range of data required, end date
#'
#' @return A tibble with data form the World Bank
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_WB_API()
#' Kenya$
#' set_wb_data(indicator_label = "C1.12")
#' }
set_wb_data = function(indicator_label, date_from = 1960,
date_to = 2022) {
indicator_name_ <- self$wb_indicators %>%
dplyr::filter(indicator == indicator_label)
if(nrow(indicator_name_) < 1)
cat("\n",
glue::glue("\rWB: '{indicator_label}' is currently unrecognised")
)
indicator_name_ <- indicator_name_ %>%
dplyr::pull(name)
tmp <- private$wb_indicators_data(
.countries_ = self$country_code['WB'],
.indicator_id_ = indicator_label,
.start_ = date_from, .end_ = date_to) %>%
private$wb_extract_data()
self$wb_data <-
if(!is.null(tmp)) {
tmp
} else {
cat("\n",
glue::glue("\rWB: '{indicator_name_}' is currently unavailable for {private$country_name}.")
)
dplyr::tibble(
" " = glue::glue("'{indicator_name_}' is currently unavailable for {private$country_name}.")
)
}
invisible(self)
},
#' @description
#' Get data from a specific survey
#'
#' @param survey DHS survey year.
#'
#' @return A tibble containing data from all country-specific DHS
#' surveys
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_DHS_API()
#' Kenya$
#' get_dhs_survey_data(
#' survey = 1989,
#' filter_var = "SurveyYear"
#' )
#' }
get_dhs_survey_data = function(survey) {
.data_ <- self$dhs_data %>%
dplyr::filter(SurveyYear %in% survey)
if(nrow(.data_) < 1) {
cat("\n",
glue::glue("\rDHS: '{survey}' is currently unrecognised. Current possible survey years include: {self$dhs_survey_years}"),
"\n"
)
}
return(.data_)
},
#' @description
#' Get data for a specific health indicator from DHS
#'
#' @param indicator_name DHS indicator name or indicator label.
#' @param filter_var Either IndicatorId (default if nothing was
#' supplied) or Indicator. This variable is used by the function to
#' filter the data accordingly.
#'
#' @return A tibble containing indicator-specific data from the
#' country's DHS surveys
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_DHS_API()
#' Kenya$
#' get_dhs_ind_data(
#' indicator_name = "FE_FRTR_W_A15",
#' filter_var = "IndicatorId"
#' )
#' }
get_dhs_ind_data = function(indicator_name, filter_var) {
if(is.null(filter_var))
filter_var <- 'Indicator'
if(!any(filter_var %in% c('IndicatorId', 'Indicator')))
stop("the supplied Indicator filtering variable is unknown")
.data_ <- self$dhs_data %>%
dplyr::filter(.data[[filter_var]] %in% indicator_name)
if(nrow(.data_) < 1) {
cat("\n",
glue::glue("\rDHS: '{indicator_name}' is currently unrecognised."),
"\n"
)
}
.data_ <- .data_ %>%
dplyr::group_by(.data[[filter_var]]) %>%
dplyr::slice_max(SurveyYear) %>%
dplyr::filter()
return(.data_)
},
#' @description
#' Get data from a specific socio-economic data from the World Bank
#'
#' @return A tibble containing the country indicator-specific data
#' fetched from the World Bank API
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_WB_API()
#' Kenya$
#' set_wb_data(indicator_label = "C1.12")$
#' get_wb_ind_data()
#' }
get_wb_ind_data = function() {
return(self$wb_data)
},
#' @description
#' Get health facilities' data
#'
#' @return A tibble containing unmodified country-specific health
#' facilities information
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_HS_API()
#' Kenya$
#' get_facilities_data()
#' }
get_facilities_data = function() {
return(self$health_facilities_data)
},
#' @description
#' Get health facilities' counts
#'
#' @return A tibble containing country-specific health facilities
#' numbers/stats by facility type
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_HS_API()
#' Kenya$
#' get_facilities_stats()
#' }
get_facilities_stats = function() {
return(self$health_facilities_stats)
},
#' @description
#' Get health facilities' map
#'
#' @return An object of class leaflet (A leaflet map)
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_HS_API()
#' Kenya$
#' get_facilities_map()
#' }
get_facilities_map = function() {
return(self$health_facilities_map)
},
#' @description
#' Get the indicators from the GHO API
#'
#' @return a tibble of GHO indicators (names and codes).
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_GHO_API()
#' Kenya$
#' get_gho_ind_list()
#' }
get_gho_ind_list = function() {
return(self$gho_indicators)
},
#' @description
#' Get country-specific indicator data for the GHO API
#'
#' @param indicator_code_ the GHO code used to refer to the indicator
#' of interest
#'
#' @return A tibble containing the indicator name, label, and value
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class Country_R6:
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#' Kenya$
#' initiate_GHO_API()
#' Kenya$
#' get_gho_ind_data(
#' indicator_code_ = "WHOSIS_000001"
#' )
#' }
get_gho_ind_data = function(indicator_code_) {
indicator_name_ <- self$gho_indicators %>%
dplyr::filter(IndicatorCode == indicator_code_[1])
if(nrow(indicator_name_) < 1) {
cat("\n",
glue::glue("\rGHO: '{indicator_code_}' is currently unrecognised."),
"\n"
)
}
indicator_name_ <- indicator_name_ %>%
dplyr::pull(IndicatorName)
API_response <- private$gho_api_query(
.query_ = "countryIndicatorData",
.query_args_ = list('indc_label_' = indicator_code_[1]),
.country_code_ = self$country_code['GHO']
)
if(!is.null(API_response))
data_ <- if(length(API_response$outputs$value) == 0){
cat("\n",
glue::glue("\rGHO: '{indicator_name_}' is currently unavailable for {private$country_name}.")
)
dplyr::tibble(
" " = glue::glue("'{indicator_name_}' is currently unavailable for {private$country_name}.")
)
} else {
private$gho_extract_data(API_response)
}
# Some indicators have two or more codes (Ambient air pollution
# attributable DALYs):
if(length(indicator_code_) > 1) {
for (i in 2:length(indicator_code_)) {
API_response <- private$gho_api_query(
.query_ = "countryIndicatorData",
.query_args_ = list('indc_label_' = indicator_code_[i]),
.country_code_ = self$country_code['GHO']
)
if(!is.null(API_response))
data_ <- if(length(API_response$outputs$value) == 0){
data_
} else {
data_ %>%
dplyr::bind_rows(
private$gho_extract_data(API_response)
)
}
}
}
self$gho_data <- data_
return(data_)
}
),
# Private elements:
private = list(
hs_API_key = "key", # healthsites API key, currently accepts anything.
country_name = NULL, # name of country for which the copy was made.
# Query the DHS API
# Website: (https://dhsprogram.com/)
#
# .query_ the name of the query to be executed.
# .country_code_ the country of interest's iso2 code.
# .page_ the API page number from which data is to be fetched.
#
# A list of objects including the raw response from the API
# in addition to parsed results.
dhs_api_query = function(.query_,
.country_code_ = self$country_code['DHS'],
.page_ = 1) {
# Append query arguments together:
url_ <- function(page_ = .page_, query_ = .query_) {
blueprint <- switch(
query_,
countryNames = "https://api.dhsprogram.com/rest/dhs/countries?returnFields=CountryName,DHS_CountryCode&f=json",
countryData = "https://api.dhsprogram.com/rest/dhs/data/{.country_code_}?page={page_}"
)
return(glue::glue(blueprint))
}
# Send request to API:
response <- httr::GET(url = url_())
httr::stop_for_status(response) # abort if request was unsuccessful
# Get results:
headers <- httr::headers(response)
# Parse results:
## Identify response encoding:
encoding <- stringi::stri_enc_detect(
httr::content(x = response, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text <- httr::content(x = response, as = "text",
encoding = encoding)
## Identify content type:
content_type <- response$headers$`content-type`
## Parse contents:
if(grepl(content_type, pattern = "json")) {
### explicitly if of type json:
parsed_response <- RJSONIO::fromJSON(parsed_text)
} else {
### automatically by httr:
parsed_response <- httr::content(x = response, as = "parsed",
encoding = encoding)
}
# Grab other pages, if additional ones exist:
if(!is.null(parsed_response[['TotalPages']])) {
tot_pages_ <- parsed_response[['TotalPages']]
if(parsed_response[['TotalPages']] > 1) {
pages_ <- 2:tot_pages_
names(pages_) <- paste("page", pages_)
env_ <- environment()
cat("\n")
purrr::walk(
.x = pages_,
.f = function(page_) {
cat(paste0("\rDHS: ", .country_code_, " - fetching page ",
page_, " of ", tot_pages_))
# Send request to API:
response_ <- httr::GET(url = url_(page_ = page_))
httr::stop_for_status(response_)
# Parse results:
## Identify response encoding:
encoding_ <- stringi::stri_enc_detect(
httr::content(x = response_, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text_ <- httr::content(x = response_, as = "text",
encoding = encoding_)
## Identify content type:
content_type_ <- response_$headers$`content-type`
## Parse contents:
if(grepl(content_type_, pattern = "json")) {
### explicitly if of type json:
parsed_response_ <- RJSONIO::fromJSON(parsed_text_)
} else {
### automatically by httr:
parsed_response_ <- httr::content(x = response_,
as = "parsed",
encoding = encoding_)
}
assign('response',
purrr::map2(
.x = response,
.y = response_,
.f = ~ c(.x, .y)
),
envir = env_)
assign('parsed_response',
purrr::map2(
.x = parsed_response,
.y = parsed_response_,
.f = ~ c(.x, .y)
),
envir = env_)
}
)
}
}
# Pack results into one list:
results <- list('outputs' = parsed_response, 'response' = response,
'headers' = headers, 'encoding' = encoding)
return(results)
},
# Extract data retrieved from the DHS API
#
# .data_ Extraction target object. A list of class
# dhs_api_data that contains the data retrieved using the
# dhs_api_query function.
#
# A tibble containing the data retrieved via the API
dhs_extract_data = function(.data_) {
data_ <- .data_$outputs$Data %>%
purrr::pmap_df(.l = ., .f = function(...) c(...))
return(data_)
},
# Query the Global Health Observatory (GHO) api
# website: (https://www.who.int/data/gho/info/gho-odata-api)
#
# .query_ the name of the query to be executed.
# .country_code_ the country of interest's iso2 code.
# .page_ the API page number from which data is to be fetched.
#
# A list of objects including the raw response from the API
# in addition to parsed results.
#
# ghoDimensions = gho_api_query(
# .query_ = "dimensions",
# .country_code_ = NULL)
# ghoCountryNames = gho_api_query(
# .query_ = "countryNames",
# .country_code_ = NULL)
# ghoIndicators = gho_api_query(
# .query_ = "indicatorsList",
# .country_code_ = NULL)
# ghoIndicatorInfo = gho_api_query(
# .query_ = "grabIndicatorInfo",
# .query_args_ =
# list('indc_name_' = "Ambient%20air%20pollution%20attributable%20deaths"),
# .country_code_ = NULL)
# ghoIndicatorSearch = gho_api_query(
# .query_ = "searchIndicators",
# .query_args_ = list('indc_key_words_' = "Household"),
# .country_code_ = NULL)
# ghoIndicatorData = gho_api_query(
# .query_ = "indicatorData",
# .query_args_ = list('indc_label_' = "WHOSIS_000001"),
# .country_code_ = NULL)
# ghoCountryIndicatorData = gho_api_query(
# .query_ = "countryIndicatorData",
# .query_args_ = list('indc_label_' = "WHOSIS_000001"),
# .country_code_ = "KEN")
gho_api_query = function(.query_,
.query_args_ = list(NULL),
.country_code_) {# = self$country_code['GHO']
# Append query arguments together:
url_ <- function(query_ = .query_,
country_code_ = .country_code_,
indc_name_ = .query_args_[['indc_name_']],
indc_key_words_ = .query_args_[['indc_key_words_']],
indc_label_ = .query_args_[['indc_label_']]) {
blueprint <- switch(
query_,
dimensions = "https://ghoapi.azureedge.net/api/Dimension/",
countryNames = "https://ghoapi.azureedge.net/api/DIMENSION/COUNTRY/DimensionValues",
indicatorsList = "https://ghoapi.azureedge.net/api/Indicator/",
grabIndicatorInfo = "https://ghoapi.azureedge.net/api/Indicator?$filter=IndicatorName%20eq%20'{indc_name_}'",
searchIndicators = "https://ghoapi.azureedge.net/api/Indicator?$filter=contains(IndicatorName,'{indc_key_words_}')",
indicatorData = "https://ghoapi.azureedge.net/api/{indc_label_}",
countryIndicatorData = "https://ghoapi.azureedge.net/api/{indc_label_}?$filter=SpatialDim%20eq%20'{country_code_}'"
)
return(glue::glue(blueprint))
}
# Send request to API:
response <- httr::GET(url = url_())
e = tryCatch({
httr::stop_for_status(response) # abort if request was unsuccessful
NULL
}, error = function(e) {
return(list('outputs' = NULL, 'error' = e, 'url' = url_()))
})
# Parse results:
## Identify response encoding:
encoding <- stringi::stri_enc_detect(
httr::content(x = response, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text <- httr::content(x = response, as = "text",
encoding = encoding)
## Identify content type:
content_type <- response$headers$`content-type`
## Parse contents:
if(grepl(content_type, pattern = "json")) {
### explicitly if of type json:
parsed_response <- RJSONIO::fromJSON(parsed_text)
} else {
### automatically by httr:
parsed_response <- httr::content(x = response, as = "parsed",
encoding = encoding)
}
# Pack results into one list:
results <- list('outputs' = parsed_response, 'error' = e,
'url' = url_())
return(results)
},
# Extract data from the GHO API
#
# .data_ Extraction target object. A list of class
# gho_api_data that contains the data retrieved using the
# gho_api_query function.
#
# A tibble containing the data retrieved via the API.
#
# ghoCountryNames = gho_api_query(
# .query_ = "countryNames",
# .country_code_ = NULL)
#
# ghoCountries = gho_extract_data(.data_ = ghoCountryNames)
gho_extract_data = function(.data_) {
data_ <- .data_$outputs$value %>%
purrr::transpose() %>%
purrr::pmap_dfr(.l = ., .f = function(...) dplyr::bind_rows(...))
return(data_)
},
# Query the Health sites API
# website: (https://healthsites.io/)
#
# .query_ The name of the query to be executed.
# .API_key_ A string of characters required to access the API
# To get one:
# 1. Establish an OpenStreetMap account:
# https://www.openstreetmap.org/user/new
# 2. Sign into Healthsites with your OSM account:
# https://healthsites.io/map
# 3. Get an API token off your profile page:
# - Click on your user profile to open your profile page
# - There you will find an option to generate/view the API-key/token
# .country_name_ the name of the country for which the API
# will be queried.
# .page_ the API page number from which data is to be fetched
#
# A list of objects including the raw response from the API
# in addition to parsed results.
hs_api_query = function(.query_,
.country_name_ = private$country_name,
.page_ = 1,
.API_key_ = private$hs_API_key) {
# Append query arguments together:
url_ <- function(page_ = .page_, query_ = .query_) {
blueprint <- switch(
query_,
country = "https://healthsites.io/api/v2/countries/autocomplete?api-key={.API_key_}&q={.country_name_}",
facilities = "https://healthsites.io/api/v2/facilities/?api-key={.API_key_}&page={page_}&country={.country_name_}"
)
return(glue::glue(blueprint))
}
# Send request to API:
response <- httr::GET(url = url_())
httr::stop_for_status(response) # abort if request was unsuccessful
# Get results:
headers <- httr::headers(response)
# Parse results:
## Identify response encoding:
encoding <- stringi::stri_enc_detect(
httr::content(x = response, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text <- httr::content(x = response, as = "text",
encoding = encoding)
## Identify content type:
content_type <- response$headers$`content-type`
## Parse contents:
if(grepl(content_type, pattern = "json")) {
### explicitly if of type json:
parsed_response <- RJSONIO::fromJSON(parsed_text)
} else {
### automatically by httr:
parsed_response <- httr::content(x = response, as = "parsed",
encoding = encoding)
}
# Pack results into one list:
results <- list('outputs' = parsed_response, 'response' = response,
'headers' = headers, 'encoding' = encoding)
return(results)
},
# Query healthsities API for all existing facilities in a country
#
# .country_name_ The name of the country to query the API
# .API_key_ Healthsities API key or token.
#
# A list of objects from recursive querying including the raw
# response from the API in addition to parsed results.
hs_facilities_query = function(.country_name_ = private$country_name,
.API_key_ = private$hs_API_key) {
loop_ <- TRUE
page_ <- 1
cat(paste0("\n\rHS: ", .country_name_, " - fetching page ", page_))
# retrieve first page of facilities:
outData_ <- private$hs_api_query(
.query_ = 'facilities',
.country_name_ = .country_name_,
.page_ = page_,
.API_key_ = .API_key_
)
# prevent looping if all available facilities were grabbed:
if(length(outData_$outputs) < 100) loop_ <- FALSE
# otherwise grab facilities in next page(s):
page_ <- page_ + 1
while (loop_) {
cat(paste0("\rHS: ", .country_name_, " - fetching page ", page_))
# use trycatch() to exit function with available data:
tryCatch(
{
# query api for next page of facilities:
inData_ <- private$hs_api_query(
.query_ = 'facilities',
.country_name_ = .country_name_,
.page_ = page_,
.API_key_ = .API_key_
)
# merge outputs:
outData_ <- purrr::map2(outData_, inData_, ~ c(.x, .y))
# exit loop if all facilities were downloaded:
if(length(inData_$outputs) == 0 |
length(inData_$outputs) < 100) loop_ <- FALSE
},
error=function(cond) {
# exit loop:
loop_ <- FALSE
}
)
page_ <- page_ + 1
}
return(outData_)
},
# Extract data from the healthsites API
#
# .data_ Extraction target object. A list of class hs_api_data
# that contains the data retrieved using the hs_xxxx_query functions
#
# A tibble containing facility information and spatial data
# in the form of simple lng/lat data
# These data can be passed to leaflet (lng/lat)
# functions to map the facilities appropriately.
hs_extract_dataset = function(.data_) {
.data_ <- .data_$outputs %>%
# expose the data in the outputs list:
purrr::transpose() %>%
# extract the contents and put them a tibble:
purrr::pmap_df(.l = ., .f = function(...) c(...)) %>%
# pivot spatial data wider to create lng/lat columns:
dplyr::mutate(coordinates_labels = rep(c('lng', 'lat'), nrow(.)/2)) %>%
tidyr::pivot_wider(names_from = coordinates_labels,
values_from = centroid.coordinates) %>%
dplyr::select(-c(dplyr::contains('coordinates'),
dplyr::contains('centroid'))) %>%
dplyr::select(c(attributes.amenity, attributes.name,
attributes.changeset_id, attributes.healthcare,
lng, lat))
return(.data_)
},
# Extract data from the healthsites API
#
# .data_ Extraction target object. A list of class hs_api_data
# that contains the data retrieved using one of the hs_xxxx_query
# functions.
# .levels_ Passed to function purrr::pluck. A list of
# accessors for indexing into the object. Can be an integer position,
# a string name, or an accessors function (except for the assignment
# variants which only support names and positions). If the object
# being indexed is an S4 object, accessing it by name will return
# the corresponding slot.
# .default_ Passed to function purrr::pluck. It is a value to
# use if target is empty or absent.
# .func_ A function from the purrr::map/purrr::pmap family to
# be used in extracting values from the target. If no function was
# supplied, the supplied function was not expected or failed to
# execute, then purrr::map is used.
#
# A vector, list or dataset based on the supplied function
# and the levels of extraction.
hs_extract_values = function(.data_, .levels_, .default_ = NULL,
.func_ = NULL) {
# use the default function "map" if non were supplied:
if(!is.null(.func_)) {
# in case an unknown map_ function was supplied, fall back to default:
tryCatch(
{
purrr::exec(
.fn = .func_,
.data_, purrr::pluck, !!!.levels_, .default = .default_)
},
error = function(e) {
message(paste0("Unable to run the supplied function [",
.func_,
"]. Using default function."))
purrr::map(
.data_, purrr::pluck, !!!.levels_,
.default = .default_)
}
)
} else {
purrr::map(
.data_, purrr::pluck, !!!.levels_,
.default = .default_)
}
},
# Visualise country data on a map
#
# .data_ A tibble containing facility information and spatial
# data in the form of (lng/lat) data.
# ... Extra arguments passed to the leaflet::leaflet map.
#
# An object of class leaflet (A leaflet map).
hs_map_facilities = function(.data_, ...) {
if(nrow(.data_) > 1) {
basemap <- leaflet::leaflet(.data_) %>%
# add different provider tiles
leaflet::addProviderTiles(
provider = "OpenStreetMap",
group = "OpenStreetMap") %>% # give the layer a name
leaflet::addProviderTiles(
provider = "CartoDB.Positron",
group = "CartoDB.Positron") %>%
leaflet::addProviderTiles(
provider = "CartoDB.DarkMatter",
group = "CartoDB.DarkMatter") %>%
# add a layers control
leaflet::addLayersControl(
baseGroups = c("OpenStreetMap", "CartoDB.Positron",
"CartoDB.DarkMatter"),
overlayGroups = c("dots","icons","icons clustered"),
# position it on the topleft
position = "topleft")
#### Icons and labels;
colours <- c("red", "orange", "beige", "green", "blue", "purple",
"pink", "cadetblue", "gray")
icons <- leaflet::awesomeIcons(
icon = "medkit",
iconColor = "white",
library = "ion",
markerColor =
colours[match(
.data_$attributes.amenity,
levels(as.factor(.data_$attributes.amenity)))] %>%
{ifelse(is.na(.), "black", .)})
labels <- sprintf(
"<strong> %s </strong> <br/> %s",
.data_$attributes.name,
.data_$attributes.amenity) %>%
purrr::map(htmltools::HTML)
makeLegend = function(map, colors, labels, shapes = "square",
sizes = 30,
borders ="black"){
legend_colors = paste0(
colors, "; width:", sizes, "px; height:",
sizes, "px; border:3px solid ", borders,
"; border-radius:", shapes)
legend_labels = paste0(
"<div style='display: inline-block;height: ",
sizes, "px;margin-top: 4px;line-height: ",
sizes, "px;'>", labels, "</div>")
return(
leaflet::addLegend(
map, colors = legend_colors,
labels = legend_labels,
group = 'Legend')
)
}
map <- basemap %>%
leaflet::addCircleMarkers(
lng = ~ lng,
lat = ~ lat,
label = ~ labels,
radius = 2,
group = "dots",
color = colours[match(
.data_$attributes.amenity,
levels(as.factor(.data_$attributes.amenity)))] %>%
{ifelse(is.na(.), "black", .)}) %>%
leaflet::addAwesomeMarkers(
lng = ~ lng,
lat = ~ lat,
icon = icons,
label = ~ labels,
group = "icons clustered",
clusterOptions = leaflet::markerClusterOptions()) %>%
leaflet::addAwesomeMarkers(
lng = ~ lng,
lat = ~ lat,
icon = icons,
group = "icons",
label = ~ labels) %>%
makeLegend(
colors =
colours[1:length(levels(
as.factor(.data_$attributes.amenity)))],
labels =
levels(
as.factor(.data_$attributes.amenity)),
shapes = "circles",
sizes = 15,) %>%
leaflet::hideGroup("icons") %>%
leaflet::hideGroup("dots")
return(map)
} else NULL
},
# Save World Bank API indicators
#
# .existing_ If TRUE (default), extract indicators from the
# WDI::WDI_data package. Otherwise, this function uses
# WDI::WDIcache() to download data via the World Bank API.
#
# A list containing two tibbles; one with World Bank API
# country names, iso2 and iso3 codes, while the second one contains
# indicator names and labels.
wb_codes_indicators = function(.existing_ = TRUE) {
if(.existing_){
list_ <- list(
'iso_codes' = WDI::WDI_data$country %>%
dplyr::as_tibble() %>%
dplyr::select(country, iso3c, iso2c),
'indicator_labels' = WDI::WDI_data$series %>%
dplyr::as_tibble() %>%
dplyr::select(indicator, name)
)
} else {
cache_ <- WDI::WDIcache()
list_ <- list(
'iso_codes' = cache_$country %>%
dplyr::as_tibble() %>%
dplyr::select(country, iso3c, iso2c),
'indicator_labels' = cache_$series %>%
dplyr::as_tibble() %>%
dplyr::select(indicator, name)
)
}
return(list_)
},
# Query the World Bank API for indicator data
# Website: (https://datahelpdesk.worldbank.org/knowledgebase)
#
# .countries_ The iso2code of the country or countries to
# query.
# .indicator_id_ Id of the indicator to query.
# .start_ Year of earliest records to query; earliest is 1960.
# .end_ Year of latest records to query.
# .latest_ Number of latest records to return, default is 1.
# .per_page_ Number of records per page, default/maximum is
# 32500.
# .page_ The page number from which to start querying the api.
#
# A list of objects including the raw response from the API
# in addition to parsed results.
wb_indicators_data = function(.countries_, .indicator_id_,
.start_ = 1960, .end_ = 2022,
.latest_ = 1, .per_page_ = 32500,
.page_ = 1) {
# Allow to query several countries:
country_ids_ <- .countries_[1]
if(length(.countries_) > 1) {
for (i in 2:length(.countries_)) {
country_ids_ <- paste0(country_ids_, ";", .countries_[i])
}
}
# Set query url:
url_ <- function(page_ = .page_)
glue::glue("https://api.worldbank.org/v2/en/country/{country_ids_}/indicator/{.indicator_id_}?format=json&date={.start_}:{.end_}&per_page={.per_page_}&page={page_}")
# Send request to API:
response <- httr::GET(url = url_())
httr::stop_for_status(response) # abort if request was unsuccessful
# Parse results:
## Identify response encoding:
encoding <- stringi::stri_enc_detect(
httr::content(x = response, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text <- httr::content(x = response, as = "text",
encoding = encoding)
## Identify content type:
content_type <- response$headers$`content-type`
## Parse contents:
if(grepl(content_type, pattern = "json")) {
### explicitly if of type json:
parsed_response <- RJSONIO::fromJSON(parsed_text)
} else {
### automatically by httr:
parsed_response <- httr::content(x = response, as = "parsed",
encoding = encoding)
}
# Grab other pages, if more exist:
if(!is.null(parsed_response[[1]][['pages']])) {
tot_pages <- parsed_response[[1]][['pages']]
if(tot_pages > 1) {
pages_ <- 2:tot_pages
names(pages_) <- paste("page", pages_)
env_ <- environment()
cat("\n")
purrr::walk(
.x = pages_,
.f = function(page_) {
cat(
glue::glue("\rWB: fetching page {page_} of {tot_pages}"))
# Send request to API:
response_ <- httr::GET(url = url_(page_ = page_))
httr::stop_for_status(response_)
# Parse results:
## Identify response encoding:
encoding_ <- stringi::stri_enc_detect(
httr::content(x = response_, as = "raw"))[[1]][1, 1]
## Parse response as text:
parsed_text_ <- httr::content(x = response_, as = "text",
encoding = encoding_)
## Identify content type:
content_type_ <- response_$headers$`content-type`
## Parse contents:
if(grepl(content_type_, pattern = "json")) {
### explicitly if of type json:
parsed_response_ <- RJSONIO::fromJSON(parsed_text_)
} else {
### automatically by httr:
parsed_response_ <- httr::content(x = response_,
as = "parsed",
encoding = encoding_)
}
assign('response',
purrr::map2(
.x = response,
.y = response_,
.f = ~ c(.x, .y)
),
envir = env_)
assign('parsed_response',
purrr::map2(
.x = parsed_response,
.y = parsed_response_,
.f = ~ c(.x, .y)
),
envir = env_)
}
)
}
}
# Pack results into one list:
results <- list('outputs' = parsed_response, 'response' = response,
'encoding' = encoding)
return(results)
},
# Extract data retrieved from the World Bank api
#
# .data_ Extraction target object. A list of class
# wb_api_data that contains the data retrieved by the
# wb_indicators_data function.
#
# A tibble containing the data retrieved via the api.
wb_extract_data = function(.data_) {
# Indicators values are missing for some countries,
# tryCatch() should help prevent errors in such occasions:
.data_ <- tryCatch({
.data_$outputs[[2]] %>%
purrr::transpose() %>%
purrr::pmap_df(.l = ., .f = function(...) c(...)) %>%
dplyr::filter(!is.na(value))
}, error = function(e) {
NULL
})
return(.data_)
}
)
)
# World R6 class: ----
#' R6 Class representing a world.
#'
#' @description
#' An instance or object of class world is expected to contain (house)
#' objects from class \link{Country_R6} The methods in this class should
#' merge the data from all added objects and summarise/present them.
#' @format An [R6::R6Class] object.
#' @name World_R6
NULL
#' @rdname World_R6
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#' }
World_R6 <- R6::R6Class(
# Object name:
classname = "World",
# Public elements:
public = list(
#' @field country_name the name of the country being added. This name
#' should be the one used in creating the Country_R6 object.
country_name = vector(),
#' @field country_data a list housing (to house) clones (copies) of
#' the instance (object) of class Country_R6 being added.
country_data = list(),
#' @field world_data a tibble containing data from all added countries
world_data = dplyr::tibble(
'attributes.amenity' = NA, 'attributes.name' = NA, 'lng' = NA,
'lat' = NA),
#' @field world_map an object of class leaflet (A leaflet map).
world_map = NULL,
#' @field world_stats a tibble containing the counts of health
#' facilities (by type)
world_stats = NULL,
#' @description
#' Add country object (of class Country_R6) to this object
#'
#' @param country_name The name of the country to which the
#' country_object will be associated
#' @param country_object An object, instance of class
#' \link{Country_R6} that contain the data from the APIs for the added
#' country.
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate a copy of class Country_R6 in the global environment:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' Kenya <- Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())
#'
#' # Query the healthsities API:
#' Kenya$
#' query_health_facilities()
#'
#' # Add a clone of the Country_R6 object \code{Kenya} to the World_R6:
#' object \code{World}
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Kenya)
#'
#' # Country_R6 object do not need to be created in the global env.
#' # Below we create an object of class Country_R6 while adding it to
#' # World_R6 object:
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#' }
add_country = function(country_name, country_object) {
names_ <- objects_ <- list()
# avoid problems if only one country name/object were supplied:
if(length(country_name) == 1) {
names_[[country_name]] <- country_name
objects_[[country_name]] <- country_object
} else {
names_ <- country_name
objects_ <- country_object
}
# allow several countries to be added at once:
purrr::walk2(
.x = names_,
.y = objects_,
.f = function(name_, object_) {
self$country_name[[name_]] <- name_
self$country_data[[name_]] <- object_
}
)
invisible(self)
},
#' @description
#' Update World data on health sites. This method is useful after an
#' object of class Country_R6 health facilities were queried
#'
#' @param country_name The name of the country for which the method
#' will update the world's data.
#'
#' @return Nothing back to the user, but updates world_data, world_map
#' and world_stats.
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate a copy of class Country_R6 within the World object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Update world data:
#' World$update_world_data(country_name = "Kenya")
#' }
update_world_data = function(country_name) {
names_ <- list()
# avoid problems if only one country name was supplied:
if(length(country_name) == 1) {
names_[[country_name]] <- country_name
} else {
names_ <- country_name
}
# allow several countries to be added at once:
purrr::walk(
.x = names_,
.f = function(name_) {
self$world_data <- tryCatch(
expr = {
if(nrow(self$
country_data[[name_]]$
health_facilities_data) > 1) {
dplyr::bind_rows(
self$world_data,
self$country_data[[name_]]$health_facilities_data %>%
dplyr::mutate('country' = name_) %>%
dplyr::distinct()
)
} else {
self$world_data
}
}, error = function(e) {
self$world_data
}
)
}
)
# compute/recompute stats:
self$world_stats <- tryCatch(
expr = {
self$world_data %>%
dplyr::filter(!is.na(country)) %>%
dplyr::count(country, attributes.amenity)
}, error = function(e) {
self$world_stats
}
)
# draw/redraw map:
self$world_map <- private$hs_map_world_facilities(self$world_data)
invisible(self)
},
#' @description
#' Get data from a specific country in the World_R6 class
#'
#' @param country_name The name of the country for which the method
#' will retrieve the data.
#'
#' @return A tibble with the specified country health sites data
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate a copy of class Country_R6 within the World object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Request some of Kenya's data back:
#' World$get_country_data(country_name = "Kenya")
#' }
get_country_data = function(country_name) {
data = self$country_data[[country_name]]$health_facilities_data
return(data)
},
#' @description
#' Get the map showing health facilities in a specific country.
#'
#' @param country_name The name of the country for which the method
#' will retrieve the map
#'
#' @return An object of class leaflet (A leaflet map)
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate a copy of class Country_R6 within the World object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Request Kenya's health facilities map:
#' World$get_country_map(country_name = "Kenya")
#' }
get_country_map = function(country_name) {
map = self$country_data[[country_name]]$health_facilities_map
return(map)
},
#' @description
#' Get the map showing health facilities in a all added country.
#'
#' @return An object of class leaflet (A leaflet map)
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate two objects of class Country_R6 within the World
#' object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#' World$add_country(
#' country_name = "Zambia",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Request available (of all included countries) health facilities
#' data:
#' World$get_world_data(country_name = "Kenya")
#' }
get_world_data = function() {
data <- self$world_data
return(data)
},
#' @description
#' Get the counts/numbers of health facilities by country name and
#' facility type.
#'
#' @return A tibble containing the request stats
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate two objects of class Country_R6 within the World
#' object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#' World$add_country(
#' country_name = "Zambia",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Request available (of all included countries) health facilities
#' stats:
#' World$get_world_stats(country_name = "Kenya")
#' }
get_world_stats = function() {
data <- self$world_stats
return(data)
},
#' @description
#' Get a map showing health facilities in all added countries
#'
#' @return An object of class leaflet (A leaflet map)
#' @export
#'
#' @examples
#' \dontrun{
#' # Instantiate a copy of class World_R6:
#' World <- World_R6$new()
#'
#' # Instantiate two objects of class Country_R6 within the World
#' object:
#' # Note: the following example assumes that the user had set their
#' # healthsites API key into their environment using set_hs_API_key()
#' World$add_country(
#' country_name = "Kenya",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#' World$add_country(
#' country_name = "Zambia",
#' country_object = Country_R6$new(
#' country_name = "Kenya",
#' hs_API_key = get_hs_API_key())$
#' query_health_facilities()
#' )
#'
#' # Request map of available health facilities from all countries
#' added to the World object
#' :
#' World$get_world_map(country_name = "Kenya")
#' }
get_world_map = function() {
map <- self$world_map
return(map)
}
),
# Private elements:
private = list(
hs_map_world_facilities = function(.data_, ...) {
# remove rows with where all values are missing:
.data_ <- .data_ %>%
dplyr::filter(!is.na(country))
# build base leaflet map:
basemap <- leaflet::leaflet(.data_) %>%
# add different provider tiles
leaflet::addProviderTiles(
provider = "OpenStreetMap",
group = "OpenStreetMap") %>% # give the layer a name
leaflet::addProviderTiles(
provider = "CartoDB.Positron",
group = "CartoDB.Positron") %>%
leaflet::addProviderTiles(
provider = "CartoDB.DarkMatter",
group = "CartoDB.DarkMatter") %>%
# add a layers control
leaflet::addLayersControl(
baseGroups = c("OpenStreetMap", "CartoDB.Positron", "CartoDB.DarkMatter"),
position = "topleft")
#### Icons and labels;
colours <- c("red", "orange", "beige", "green", "blue", "purple",
"pink", "cadetblue", "gray")
icons <- leaflet::awesomeIcons(
icon = "medkit",
iconColor = "white",
library = "ion",
markerColor =
colours[match(
.data_$attributes.amenity,
levels(as.factor(.data_$attributes.amenity)))] %>%
{ifelse(is.na(.), "black", .)})
labels <- sprintf(
"<strong> %s </strong> <br/> %s",
.data_$attributes.name,
.data_$attributes.amenity) %>%
purrr::map(htmltools::HTML)
makeLegend = function(map, colors, labels, shapes = "square",
sizes = 30,
borders ="black"){
legend_colors = paste0(colors, "; width:", sizes, "px; height:",
sizes, "px; border:3px solid ", borders,
"; border-radius:", shapes)
legend_labels = paste0("<div style='display: inline-block;height: ",
sizes, "px;margin-top: 4px;line-height: ",
sizes, "px;'>", labels, "</div>")
return(leaflet::addLegend(map, colors = legend_colors,
labels = legend_labels, group = 'Legend'))
}
map <- basemap %>%
leaflet::addAwesomeMarkers(
lng = ~ lng, lat = ~ lat,
icon = icons,
label = ~ labels,
clusterOptions = leaflet::markerClusterOptions())
return(map)
}
)
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.