suppressPackageStartupMessages(library(DSIR))
suppressPackageStartupMessages(library(dplyr))
stopifnot(packageVersion("DSIR") >= "0.10.0")The first DSIR post introduced a shared format for WHO GHO and UN SDG data. DSIR 0.10.0 adds ways to inspect and keep the detail behind each observation: population breakdowns, units, sources, and notes. Both cleaners still return the same 15 columns by default.
These examples require DSIR 0.10.0 or later and dplyr. See the public repository for installation instructions. The first two examples call the live UN SDG API; the displayed results were retrieved on 4 October 2026.
1. Look up official dimension codes
sdg_dimensions() reads series-specific code lists without downloading observations. include_attributes = TRUE also includes attributes such as units and data nature. Here we inspect age and sex codes for the SDG 3.8.2 series used below.
codebook <- suppressMessages(sdg_dimensions(
"3.8.2", series = "SH_OOP_XPD_EARNNET40",
include_attributes = TRUE
))
stopifnot(nrow(codebook) > 0L)
codebook %>%
filter(kind == "dimension", dimension %in% c("Age", "Sex")) %>%
select(dimension, code, label, sdmx) %>%
head(8L)# A tibble: 6 × 4
dimension code label sdmx
<chr> <chr> <chr> <chr>
1 Age 0-59 under 59 years old Y0T59
2 Age 60+ 60 years old and over Y_GE60
3 Age ALLAGE All age ranges or no breaks by age _T
4 Sex BOTHSEX Both sexes _T
5 Sex FEMALE Female F
6 Sex MALE Male M
Use code in filters: the alternative sdmx representation can differ. A category in the codebook does not guarantee observations for every country.
2. Select a stratum and retain its context
This follows the documented national-total example for the Philippines. Dimension names and codes are exact and case-sensitive.
national.raw <- suppressMessages(sdg_data(
"3.8.2", area = "PHL",
series = "SH_OOP_XPD_EARNNET40",
dimensions = list(
Age = "ALLAGE", Location = "ALLAREA", Sex = "BOTHSEX",
Quantile = "_T", Type_of_household = "_T"
)
))
stopifnot(nrow(national.raw) > 0L)
national <- sdg_clean(
national.raw, keep_dimensions = TRUE, keep_metadata = TRUE
)
national %>%
select(iso3, year, value_num, dim_sex, attr_units, attr_nature) %>%
tail(5L)# A tibble: 5 × 6
iso3 year value_num dim_sex attr_units attr_nature
<chr> <int> <dbl> <chr> <chr> <chr>
1 PHL 2012 36.8 BOTHSEX PERCENT G
2 PHL 2015 35.2 BOTHSEX PERCENT G
3 PHL 2018 31.6 BOTHSEX PERCENT C
4 PHL 2021 33.8 BOTHSEX PERCENT C
5 PHL 2023 31.0 BOTHSEX PERCENT C
keep_dimensions = TRUE appends named SDG columns such as dim_age and dim_sex; dim1 through dim3 remain GHO-only positions. keep_metadata = TRUE retains observation attributes, source and time context, and all footnotes and linked codes. Notes and linked codes are list-columns. See sdg_clean().
The filters run locally after all pages are downloaded. They do not reduce the number of pages fetched. DSIR checks declared page numbers, page counts, and total row counts before filtering. An inconsistent or incomplete download warns and returns no rows; counts omitted by the API cannot be verified. A requested dimension absent from the response also warns and returns no rows. sdg_coverage() accepts the same filters and now retains download warnings.
3. Save the result for reuse
snapshot(), added in 0.9.0, saves an expression’s result as an RDS file. RDS preserves the list-columns above. The second call proves that an existing snapshot is read without evaluating the expression again.
snapshot.path <- file.path(tempdir(), "sdg-3-8-2-phl-national.rds")
saved <- suppressMessages(snapshot(national, file = snapshot.path))
reused <- suppressMessages(snapshot(
stop("This expression should not run."), file = snapshot.path
))
identical(saved, reused)[1] TRUE
For reuse across R sessions, choose a fixed path in your project instead of tempdir(). refresh = TRUE re-evaluates the expression; put an API pull inside that expression when a refresh should download data again. An empty refresh is never written over a good snapshot; the older result is returned with a warning.
Other changes worth knowing
For GHO, gho_clean() can now retain each row’s dimension types (dim1_type through dim3_type), identifiers, source codes, time context, update timestamps, and comments. Types are copied from source fields rather than inferred from codes. bind_indicators() now preserves extra columns and fills missing fields when inputs have different dimensions.
Version 0.9.0 also added age_standardize() for direct age standardization with optional Fay-Feuer gamma confidence intervals, and life_table() for period life tables from age-specific mortality rates. The release notes describe the full changes.