#===============================================================================
# Option 1
#===============================================================================
# install or load required packages
pacman::p_load(
purrr, # Functional iteration (e.g. map)
httr, # HTTP requests (e.g. GET)
jsonlite, # Parse JSON from APIs
cli # Styled console messages
)
#' Check DHS Indicator List from API
#'
#' @param countryIds DHS country code(s), e.g., "EG"
#' @param indicatorIds Specific indicator ID(s)
#' @param surveyIds Survey ID(s)
#' @param surveyYear Exact year
#' @param surveyYearStart Start of year range
#' @param surveyYearEnd End of year range
#' @param surveyType DHS survey type (e.g., "DHS", "MIS")
#' @param surveyCharacteristicIds Filter by survey characteristic ID
#' @param tagIds Filter by tag ID
#' @param returnFields Fields to return (default: IndicatorId, Label, Definition)
#' @param perPage Max results per page (default = 500)
#' @param page Specific page to return (default = 1)
#' @param f Format (default = "json")
#'
#' @return A data.frame of indicators
#' @export
check_dhs_indicators <- function(
countryIds = NULL,
indicatorIds = NULL,
surveyIds = NULL,
surveyYear = NULL,
surveyYearStart = NULL,
surveyYearEnd = NULL,
surveyType = NULL,
surveyCharacteristicIds = NULL,
tagIds = NULL,
returnFields = c("IndicatorId", "Label", "Definition", "MeasurementType"),
perPage = NULL,
page = NULL,
f = "json"
) {
# Base URL
base_url <- "https://api.dhsprogram.com/rest/dhs/indicators?"
# Build query string
params <- list(
countryIds = countryIds,
indicatorIds = indicatorIds,
surveyIds = surveyIds,
surveyYear = surveyYear,
surveyYearStart = surveyYearStart,
surveyYearEnd = surveyYearEnd,
surveyType = surveyType,
surveyCharacteristicIds = surveyCharacteristicIds,
tagIds = tagIds,
returnFields = paste(returnFields, collapse = ","),
perPage = perPage,
page = page,
f = f
)
# Drop NULLs and encode
query <- paste(
purrr::compact(params) |>
purrr::imap_chr(
~ paste0(.y, "=", URLencode(as.character(.x), reserved = TRUE))
),
collapse = "&"
)
# Full URL
full_url <- paste0(base_url, query)
# Fetch with progress bar
response <- httr::GET(full_url, httr::progress())
jsonlite::fromJSON(httr::content(
response,
as = "text",
encoding = "UTF-8"
))$Data
}
#' Query DHS API Directly via URL Parameters
#'
#' Builds and queries DHS API for indicator data using URL-based access
#' instead of rdhs package.
#'
#' @param countryIds Comma-separated DHS country code(s), e.g., "SL"
#' @param indicatorIds Comma-separated DHS indicator ID(s), e.g., "CM_ECMR_C_U5M"
#' @param surveyIds Optional comma-separated survey ID(s), e.g., "SL2016DHS"
#' @param surveyYear Optional exact survey year, e.g., "2016"
#' @param surveyYearStart Optional survey year range start
#' @param surveyYearEnd Optional survey year range end
#' @param breakdown One of: "national", "subnational", "background", "all"
#' @param f Format to return (default is "json")
#'
#' @return A data.frame containing the `Data` portion of the API response.
#' @export
download_dhs_indicators <- function(
countryIds,
indicatorIds,
surveyIds = NULL,
surveyYear = NULL,
surveyYearStart = NULL,
surveyYearEnd = NULL,
breakdown = "subnational",
f = "json"
) {
# Base URL
base_url <- "https://api.dhsprogram.com/rest/dhs/data?"
# Assemble query string
query <- paste0(
"breakdown=",
breakdown,
"&indicatorIds=",
indicatorIds,
"&countryIds=",
countryIds,
if (!is.null(surveyIds)) paste0("&surveyIds=", surveyIds),
if (!is.null(surveyYear)) paste0("&surveyYear=", surveyYear),
if (!is.null(surveyYearStart)) paste0("&surveyYearStart=", surveyYearStart),
if (!is.null(surveyYearEnd)) paste0("&surveyYearEnd=", surveyYearEnd),
"&lang=en&f=",
f
)
full_url <- paste0(base_url, query)
cli::cli_alert_info("Downloading DHS data...")
response <- httr::GET(full_url, httr::progress())
if (httr::http_error(response)) {
stop("API request failed: ", httr::status_code(response))
}
content_raw <- httr::content(response, as = "text", encoding = "UTF-8")
data <- jsonlite::fromJSON(content_raw)$Data
cli::cli_alert_success("Download complete: {nrow(data)} records retrieved.")
return(data)
}
# get available indicators
indicators <- check_dhs_indicators(
countryIds = "SL",
surveyYear = 2019,
surveyType = "DHS",
returnFields = c("IndicatorId", "Label", "MeasurementType"),
)
# filter to find ITN-related indicators
indicators |>
dplyr::filter(stringr::str_detect(Label, "ITN"))
# get the DHS shapefile
sle_dhs_shp <- sf::read_sf(
here::here(
"01_foundational/1a_administrative_boundaries",
"1ai_adm2",
"sdr_subnational_boundaries_adm2.shp"
)
) |>
dplyr::select(
adm1 = OTHREGNA,
adm2 = DHSREGEN,
adm2_code = REG_ID
)
# get pre-aggregated ITN access data at subnationl
itn_access_data <- download_dhs_indicators(
countryIds = "SL",
surveyYear = 2019,
indicatorIds = "ML_NETP_H_ITN",
breakdown = "subnational"
)
# join indicator with shapefile
indicator_adm2 <- itn_access_data |>
dplyr::inner_join(
sle_dhs_shp,
by = c("RegionId" = "adm2_code")
) |>
sf::st_as_sf() |>
dplyr::select(
survey_id = SurveyId,
adm1,
adm2,
adm2_code = RegionId,
prop = Value,
indicator = Indicator
)
# check indicator
sf::st_drop_geometry(indicator_adm2)
# get shapefile
sle_diff_shp <- sf::read_sf(
here::here(
"01_foundational/1a_administrative_boundaries",
"1ai_adm2",
"2021.shp"
)
) |>
dplyr::select(
adm1 = FIRST_REGI,
adm2 = FIRST_DNAM
)
sle_dhs_shp <- sf::read_sf(
here::here("english/data_r/DHS/sdr_subnational_boundaries_adm2.geojson")
) |>
dplyr::select(
adm1 = OTHREGNA,
adm2 = DHSREGEN,
adm2_code = REG_ID
)
# clean admin labels in indicator data
itn_access_data2 <- itn_access_data |>
dplyr::mutate(
label_updated = dplyr::case_when(
CharacteristicLabel == "..Kailahun" ~ "KAILAHUN",
CharacteristicLabel == "..Kenema" ~ "KENEMA",
CharacteristicLabel == "..Kono" ~ "KONO",
CharacteristicLabel == "....Koinadugu" ~ "KOINADUGU",
CharacteristicLabel == "..Tonkolili" ~ "TONKOLILI",
CharacteristicLabel == "..Kambia" ~ "KAMBIA",
CharacteristicLabel == "..Karene" ~ "KARENE",
CharacteristicLabel == "..Bombali" ~ "BOMBALI",
CharacteristicLabel == "....Falaba" ~ "FALABA",
CharacteristicLabel == "..Port Loko" ~ "PORT LOKO",
CharacteristicLabel == "..Bo" ~ "BO",
CharacteristicLabel == "..Bonthe" ~ "BONTHE",
CharacteristicLabel == "..Moyamba" ~ "MOYAMBA",
CharacteristicLabel == "..Pujehun" ~ "PUJEHUN",
CharacteristicLabel == "..Western Rural" ~ "WESTERN RURAL",
CharacteristicLabel == "..Western Urban" ~ "WESTERN URBAN",
CharacteristicLabel == "Eastern" ~ "EASTERN",
CharacteristicLabel == "Northern" ~ "NORTHERN",
CharacteristicLabel == "North Western" ~ "NORTHERN",
CharacteristicLabel == "Western" ~ "WESTERN",
CharacteristicLabel == "Southern" ~ "SOUTHERN",
TRUE ~ NA
)
)
# join cleaned indicator data to shapefile using admin2
itn_access_data2_joined <- itn_access_data2 |>
dplyr::inner_join(sle_diff_shp, by = c("label_updated" = "adm2"))
# clean up columns
final_indicator_df <-
itn_access_data2_joined |>
sf::st_as_sf() |>
dplyr::select(
survey_id = SurveyId,
adm1,
adm2 = label_updated,
adm2_code = RegionId,
prop = Value,
indicator = Indicator
)
# calculate number of unique shapefile districts matched in final data
n_shp_total <- dplyr::n_distinct(sle_diff_shp$adm2)
n_shp_matched <- dplyr::n_distinct(final_indicator_df$adm2)
cli::cli_alert_success(
"{n_shp_matched} out of {n_shp_total} shapefile districts matched in the final joined dataset."
)
cat("\n")
# view distinct mappings used in join
itn_access_data2_joined |>
dplyr::distinct(CharacteristicLabel, label_updated)
# define save directory
save_path <- here::here("1.6_health_systems/1.6a_dhs")
#| # Save final joined ITN indicators with spatial data
rio::export(
indicator_adm2 |> sf::st_drop_geometry(),
here::here(save_path, "processed", "itn_adm2_indicator.csv")
)
rio::export(
indicator_adm2,
here::here(save_path, "processed", "itn_adm2_indicator.rds")
)
#===============================================================================
# Option 2a
#===============================================================================
# install or load required packages
pacman::p_load(
rdhs # DHS API access and dataset management
)
# Set configuration
rdhs::set_rdhs_config(
email = "my_email_address@gmail.com",
project = "SNT for SL",
config_path = "rdhs.json",
cache_path = here::here("1.6_health_systems/1.6a_dhs"),
data_frame = "data.table::as.data.table",
global = FALSE,
password_prompt = TRUE,
verbose_setup = TRUE,
timeout = 120,
verbose_download = TRUE
)
# Pull filenames for 2016 DHS and 2019 DHS MIS in Sierra Leone
data_filename <- rdhs::dhs_datasets(
countryIds = "SL",
surveyYear = c("2016", "2019"),
fileType = c("PR", "HR", "KR"),
surveyType = c("DHS", "MIS"),
fileFormat = "FLAT"
) |>
dplyr::group_by(DatasetType, CountryName, FileType) |>
dplyr::distinct(FileName) |>
dplyr::pull(FileName)
# Download and save the datasets as .rds
rdhs::get_datasets(
dataset_filenames = data_filename,
download_option = "rds",
output_dir_root = here::here("1.6_health_systems/1.6a_dhs/raw"),
clear_cache = TRUE
)
# Download and save the datasets as .rds
rdhs::get_datasets(
dataset_filenames = data_filename,
download_option = "rds",
output_dir_root = here::here("1.6_health_systems/1.6a_dhs/raw"),
clear_cache = TRUE
)
#===============================================================================
# Option 2a
#===============================================================================
# install or load required packages
pacman::p_load(
haven, # For importing different types files
sf, # For importing shapefiles files
mdbr # For importing microsoft database files
)
# read Stata file (e.g., Household Recode)
hr_data <- haven::read_dta(
here::here("1.6_health_systems/1.6a_dhs/raw/SLHR7AFL/SLHR7AFL.DTA")
)
# read SPSS file
hr_data <- haven::read_sav(
here::here("1.6_health_systems/1.6a_dhs/raw/SLHR7AFL/SLHR7AFL.SAV")
)
# read SAS file
hr_data <- haven::read_sas(
here::here("1.6_health_systems/1.6a_dhs/raw/SLHR7AFL/SLHR7AFL.SAS7BDAT")
)
# read .DBF shapefile
gps_data <- sf::st_read(
here::here("1.6_health_systems/1.6a_dhs/raw/SLGE7AFL/SLGE7AFL.DBF")
)
# read .MDB shapefile
gps_data <- mdbr::read_mdb(
here::here("1.6_health_systems/1.6a_dhs/raw/SLGE7AFL/SLGE7AFL.MDB"),
table = "GEOGRAPHIC"
)
#===============================================================================
# End of Script
#===============================================================================