| Title: | Data Science Infrastructure for Global Health |
|---|---|
| Description: | Supports global health data analysis, including a publication-ready 'ggplot2' theme, a 'flextable' defaults helper, a thin pie chart wrapper, built-in regional country-code datasets with a WHO region lookup helper, a geometric mean function for indicator aggregation, an average annual rate of reduction function for indicator progress tracking, direct age standardization against the bundled WHO 2026 Standard Population, period life-table construction, a snapshot helper for reproducible data pulls, and convenience clients for the World Health Organization Global Health Observatory (GHO) through its legacy OData API <https://ghoapi.azureedge.net/api/> or the public WHO xMart OData API <https://xmart-api-public.who.int/DATA_>, Global Health Estimates (GHE) through WHO xMart, and the United Nations Sustainable Development Goals (SDG) API <https://unstats.un.org/SDGAPI/swagger/>. |
| Authors: | Shanlong Ding [aut, cre] (ORCID: <https://orcid.org/0000-0001-9048-6670>) |
| Maintainer: | Shanlong Ding <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.11.0 |
| Built: | 2026-10-19 01:41:51 UTC |
| Source: | https://github.com/shanlong-who/dsir |
Computes the average annual rate of reduction of an indicator over time — the standard WHO / UNICEF metric for tracking progress in declining indicators such as maternal, neonatal, and under-five mortality, stunting prevalence, or premature NCD mortality.
aarr(year, value, method = c("regression", "endpoint"), na.rm = TRUE)aarr(year, value, method = c("regression", "endpoint"), na.rm = TRUE)
year |
Numeric vector of years. |
value |
Numeric vector of indicator values, the same length as
|
method |
Character. |
na.rm |
Logical. Should pairs with a missing |
Two estimation methods are offered:
"regression" (default; the UNICEF-recommended approach): an
ordinary least-squares line is fitted to log(value) against
year, and the AARR is 1 - exp(b), where b is the fitted
slope. All observations contribute, so the estimate is robust to
noise in individual years.
"endpoint": only the earliest and latest years are used:
1 - (v1 / v0) ^ (1 / (y1 - y0)), where v0 and v1 are the
values at the earliest year y0 and the latest year y1.
Intermediate observations are ignored. If several observations
share the earliest or latest year, their mean is used (but see
the note on duplicated years below).
Sign convention. A positive AARR means the indicator is
declining (progress, for a mortality-type indicator): 0.024
means an average decline of 2.4% per year. A negative AARR means
the indicator is increasing. Note this is the reverse of a growth
rate.
Duplicated years usually mean the data still mix several strata
— for example both sexes plus male / female in dim1, or several
series codes in data cleaned by gho_clean() / sdg_clean().
aarr() warns and proceeds (the regression pools the strata), but
you almost always want to filter to a single stratum first.
Relation to published figures. Published WHO / UNICEF tables
print the AARR as a percentage (4.4 meaning 4.4% per year);
multiply the value returned by this function by 100 to compare.
Note also that WHO's Trends in Maternal Mortality reports print a
continuous-time rate, -log(v1 / v0) / (y1 - y0) (there called
ARR), which agrees closely but not exactly with the discrete AARR
computed here — small differences from those tables are expected.
A numeric scalar: the average annual rate of reduction as a
fraction (0.024 = 2.4% per year). Multiply by 100 to compare
with published WHO / UNICEF tables, which print percentages.
Returns NA_real_ (with a warning) when fewer than two distinct
years remain after NA handling, when any value is zero or
negative, or when year or value contains non-finite values.
geomean() for ratio-based indicator aggregation.
# A perfectly exponential 2.4%/yr decline recovers exactly 0.024 years <- 2000:2015 values <- 100 * (1 - 0.024) ^ (years - 2000) aarr(years, values) # 0.024 100 * aarr(years, values) # 2.4 — as printed in reports # Endpoint method uses only the earliest and latest years aarr(years, values, method = "endpoint") # also 0.024 here # An increasing indicator gives a negative AARR aarr(2010:2020, 50 * 1.01 ^ (0:10)) # about -0.01 # Back-of-envelope projection to 2030 at the observed AARR r <- aarr(years, values) values[length(values)] * (1 - r) ^ (2030 - 2015)# A perfectly exponential 2.4%/yr decline recovers exactly 0.024 years <- 2000:2015 values <- 100 * (1 - 0.024) ^ (years - 2000) aarr(years, values) # 0.024 100 * aarr(years, values) # 2.4 — as printed in reports # Endpoint method uses only the earliest and latest years aarr(years, values, method = "endpoint") # also 0.024 here # An increasing indicator gives a negative AARR aarr(2010:2020, 50 * 1.01 ^ (0:10)) # about -0.01 # Back-of-envelope projection to 2030 at the observed AARR r <- aarr(years, values) values[length(values)] * (1 - r) ^ (2030 - 2015)
Computes a directly age-standardized rate: the rate that would be observed in a population with the age structure of a chosen standard. Direct standardization removes the effect of differing age distributions, so rates from different populations (countries, sexes, time periods) become comparable.
age_standardize( count, pop, stdpop, per = 1e+05, ci = FALSE, conf_level = 0.95, na.rm = TRUE )age_standardize( count, pop, stdpop, per = 1e+05, ci = FALSE, conf_level = 0.95, na.rm = TRUE )
count |
Numeric vector of event counts (e.g. deaths) per age group. |
pop |
Numeric vector of population denominators per age group, the
same length as |
stdpop |
Numeric vector of standard-population weights per age
group, the same length as |
per |
Numeric. The rate is expressed per this many people. Default
|
ci |
Logical. Return a confidence interval (Fay-Feuer gamma
method)? Default |
conf_level |
Numeric in (0, 1). Confidence level for the interval.
Default |
na.rm |
Logical. Drop age groups with a missing |
The age-specific rate in group is
(count / pop). With standard weights (from stdpop,
normalized to sum to 1), the standardized rate is
The three vectors count, pop, and stdpop must be aligned: element
of each refers to the same age group, in the same order.
stdpop may be supplied as counts, a standard million, or percentages
— only its relative values matter, because it is normalized internally.
The built-in who_std_pop dataset supplies the WHO 2026 Standard.
Confidence interval. With ci = TRUE, a confidence interval is
returned using the gamma-distribution method of Fay and Feuer (1997),
which has good coverage even when rates are based on small numbers of
events. This is the method used by, for example, epitools. The
interval requires the age-specific event counts, so it is only
available when count and pop are supplied (not a pre-computed
rate).
When ci = FALSE, a numeric scalar: the standardized rate per
per. When ci = TRUE, a named numeric vector with elements
rate, lower, and upper, all per per. Returns NA (scalar or
in each element) with a warning when no age groups remain after NA
handling.
World Health Organization (2026). Revised WHO standard population for calculating age-standardized rates. WHO/HSA/DDA/GHE/2026.4.
Fay MP, Feuer EJ (1997). Confidence intervals for directly standardized rates: a method based on the gamma distribution. Statistics in Medicine 16(7):791-801.
who_std_pop for the WHO 2026 Standard Population;
geomean() for ratio-based aggregation.
# Five aligned age groups with illustrative standard weights. deaths <- c(20, 15, 40, 90, 220) pop <- c(12000, 11000, 9000, 7000, 3000) w <- c(0.35, 0.25, 0.20, 0.12, 0.08) # standard weights age_standardize(deaths, pop, w) # per 100,000 age_standardize(deaths, pop, w, per = 1000) # per 1,000 # With a 95% confidence interval age_standardize(deaths, pop, w, ci = TRUE) # Using all 18 WHO 2026 groups, aligned with the observed data. deaths18 <- seq_len(nrow(who_std_pop)) pop18 <- rep(10000, nrow(who_std_pop)) age_standardize(deaths18, pop18, who_std_pop$std_million)# Five aligned age groups with illustrative standard weights. deaths <- c(20, 15, 40, 90, 220) pop <- c(12000, 11000, 9000, 7000, 3000) w <- c(0.35, 0.25, 0.20, 0.12, 0.08) # standard weights age_standardize(deaths, pop, w) # per 100,000 age_standardize(deaths, pop, w, per = 1000) # per 1,000 # With a 95% confidence interval age_standardize(deaths, pop, w, ci = TRUE) # Using all 18 WHO 2026 groups, aligned with the observed data. deaths18 <- seq_len(nrow(who_std_pop)) pop18 <- rep(10000, nrow(who_std_pop)) age_standardize(deaths18, pop18, who_std_pop$std_million)
Combines two or more tibbles produced by gho_clean() or
sdg_clean() or ghe_clean() into a single tibble. All cleaners output the
same 15-column core schema. The result is a uniform table that can be
filtered, joined, or visualised without source-specific code paths;
use the source column to identify GHO, SDG and GHE rows.
bind_indicators(...)bind_indicators(...)
... |
Two or more tibbles returned by |
Inputs do not need to be in any particular order. NULL inputs are
silently dropped, which makes it ergonomic to write code like
bind_indicators(maybe_gho, maybe_sdg) where some sources may not
have been fetched.
Additional columns, including named dimensions from
sdg_clean(keep_dimensions = TRUE), are preserved. Columns absent
from an input are filled with typed missing values. Binding rows
does not harmonise dimension codes or indicator definitions across
sources.
gho_clean(keep_metadata = TRUE) retains a row-level provider column
so legacy and xMart GHO observations remain distinguishable after binding.
Binding does not merge the input who_provenance attributes; preserve raw
pulls or snapshots when request-level provenance is needed.
A single tibble with the unified cleaned-
indicator schema (15 core columns), followed by any additional
columns in first-seen order. Row order is c(input_1, input_2, ...),
preserving within-input order.
gho_clean(), sdg_clean(), ghe_clean().
gho <- gho_data("NCDMORT3070", area = wpro_cty) |> gho_clean() sdg <- sdg_data("3.4.1", area = wpro_cty) |> sdg_clean() bind_indicators(gho, sdg)gho <- gho_data("NCDMORT3070", area = wpro_cty) |> gho_clean() sdg <- sdg_data("3.4.1", area = wpro_cty) |> sdg_clean() bind_indicators(gho, sdg)
Applies a consistent set of flextable formatting defaults for
publication-ready tables (booktabs theme, bold headers, modest
padding). Pick any font you like — the default "" leaves the
flextable default in place so the call is safe on systems where
Cambria is not installed.
dsi_flextable_defaults( font_size = 12, font_family = "", font_color = "#333333", border_color = "black", padding = c(3, 3, 4, 4) )dsi_flextable_defaults( font_size = 12, font_family = "", font_color = "#333333", border_color = "black", padding = c(3, 3, 4, 4) )
font_size |
Font size in points. Default |
font_family |
Font family name. Default |
font_color |
Font color. Default |
border_color |
Border color. Default |
padding |
Numeric vector of length 1 (applied to all sides)
or length 4 ( |
Invisibly returns NULL. Called for its side effect of
mutating the flextable global defaults via
flextable::set_flextable_defaults().
dsi_flextable_defaults()dsi_flextable_defaults()
Computes the geometric mean of a numeric vector, with optional weights. Useful for aggregating multiplicative quantities such as ratio-based health indicators (e.g. UHC service-coverage tracers, where the composite index is the geometric mean of component coverage values).
geomean(x, w = NULL, na.rm = TRUE)geomean(x, w = NULL, na.rm = TRUE)
x |
A numeric vector. Zeros produce a result of |
w |
Optional numeric vector of weights, the same length as
|
na.rm |
Logical. Should missing values in |
Pass w to compute a weighted geometric mean, defined as
exp(weighted.mean(log(x), w)).
A numeric scalar. Returns NA_real_ when the input is
empty, when it is entirely NA, or when na.rm = FALSE and
any element is NA. Returns NaN with a warning when x
contains negative values, or when all weights are zero.
# Unweighted geomean(c(1, 4, 16)) # 4 geomean(c(0.6, 0.8, 0.95)) # ~0.772 — typical UHC tracer aggregation geomean(c(1, NA, 4)) # 2 geomean(c(1, NA, 4), na.rm = FALSE) # NA_real_ geomean(c(1, 0, 4)) # 0 # Weighted geomean(c(1, 4, 16), w = c(1, 1, 1)) # 4 (equal weights = unweighted) geomean(c(1, 4, 16), w = c(1, 2, 1)) # weighted toward 4 geomean(c(0.6, 0.8, 0.95), w = c(2, 1, 1))# Unweighted geomean(c(1, 4, 16)) # 4 geomean(c(0.6, 0.8, 0.95)) # ~0.772 — typical UHC tracer aggregation geomean(c(1, NA, 4)) # 2 geomean(c(1, NA, 4), na.rm = FALSE) # NA_real_ geomean(c(1, 0, 4)) # 0 # Weighted geomean(c(1, 4, 16), w = c(1, 1, 1)) # 4 (equal weights = unweighted) geomean(c(1, 4, 16), w = c(1, 2, 1)) # weighted toward 4 geomean(c(0.6, 0.8, 0.95), w = c(2, 1, 1))
Builds a pie chart from a data frame using one categorical column and one numeric column. Slices are labeled with the category name and percentage share.
ggpie( df, .x, .y, .offset = 1, .color = "white", .legend = FALSE, .label = TRUE, .label_size = 3.5 )ggpie( df, .x, .y, .offset = 1, .color = "white", .legend = FALSE, .label = TRUE, .label_size = 3.5 )
df |
A data frame. |
.x |
Column name (string) of the categorical variable used for the slices. |
.y |
Column name (string) of the numeric variable used for the slice values. |
.offset |
Numeric scalar (> 0). Controls label position
along the slice radius. Default |
.color |
Border color between slices. Default |
.legend |
Logical. Show the legend? Default |
.label |
Logical. Draw |
.label_size |
Label text size in mm. Default |
A ggplot object.
df <- data.frame( category = c("A", "B", "C"), value = c(40, 35, 25) ) ggpie(df, "category", "value")df <- data.frame( category = c("A", "B", "C"), value = c(40, 35, 25) ) ggpie(df, "category", "value")
Lists causes from an all-age, both-sex reference slice in the latest GHE
year. The reference country is the first available WHO Member State in
ISO3 order. This avoids grouping the full database. Codes are exact
download identifiers; selection coverage still needs ghe_coverage().
ghe_causes(search = NULL)ghe_causes(search = NULL)
search |
Optional words matched against cause names, ignoring case. All terms must match; a single string is split on whitespace. |
A tibble with cause_code, cause_name, level, cause_group,
rankable, and single_cause. The provider has no parent-code field;
cause_group is retained as published and is not a parent identifier.
ghe_causes('diabetes') ghe_causes('stroke')ghe_causes('diabetes') ghe_causes('stroke')
Converts ghe_data() output for bind_indicators(). A GHE cause is id,
the selected measure is series, sex is dim1, and age is dim2.
Use keep_dimensions = TRUE to retain named sex/age, cause hierarchy and
unit, preventing information loss when combining multiple measures.
ghe_clean(df, keep_dimensions = FALSE)ghe_clean(df, keep_dimensions = FALSE)
df |
A data frame from |
keep_dimensions |
Append |
A tibble in the unified schema, with source = "ghe".
ghe_data('PHL', year = 2023, age = 'TOTAL', sex = 'TOTAL', cause = 0, measure = 'deaths') |> ghe_clean(keep_dimensions = TRUE)ghe_data('PHL', year = 2023, age = 'TOTAL', sex = 'TOTAL', cause = 0, measure = 'deaths') |> ghe_clean(keep_dimensions = TRUE)
Fetches only identifiers, geography and year, respecting sex, age and cause filters. Counts refer to source observations before measure pivoting.
ghe_coverage( area = NULL, year = NULL, year_from = NULL, year_to = NULL, sex = NULL, age = NULL, cause = NULL )ghe_coverage( area = NULL, year = NULL, year_from = NULL, year_to = NULL, sex = NULL, age = NULL, cause = NULL )
area |
ISO3 country/area codes. See |
year |
Integer years; mutually exclusive with a year range. |
year_from, year_to
|
Inclusive scalar year bounds. |
sex |
Exact codes, e.g. |
age |
Exact age codes, e.g. |
cause |
Exact cause codes from |
A tibble with location, year_min, year_max, n_years,
and n_obs. Empty selections or failures return the same typed schema.
ghe_coverage(area = 'PHL', age = 'TOTAL', sex = 'TOTAL', cause = 0)ghe_coverage(area = 'PHL', age = 'TOTAL', sex = 'TOTAL', cause = 0)
Retrieves current GHE estimates from DEX_CMS/GHE_FULL on the public
production xMart host, without credentials. Returns one row per selected
measure and country/year/sex/age/cause combination. Filters run server-side.
ghe_data( area = NULL, year = NULL, year_from = NULL, year_to = NULL, sex = NULL, age = NULL, cause = NULL, measure = NULL )ghe_data( area = NULL, year = NULL, year_from = NULL, year_to = NULL, sex = NULL, age = NULL, cause = NULL, measure = NULL )
area |
ISO3 country/area codes. See |
year |
Integer years; mutually exclusive with a year range. |
year_from, year_to
|
Inclusive scalar year bounds. |
sex |
Exact codes, e.g. |
age |
Exact age codes, e.g. |
cause |
Exact cause codes from |
measure |
Codes from |
Supply at least one filter. Queries over 1,000,000 source rows warn and
return no rows; narrow the selection or explicitly set
options(DSIR.who_max_rows = ...). This limit applies before pivoting
measures. Completeness is checked across pages; failed or incomplete
downloads return an empty tibble with a warning. No legacy fallback occurs.
Counts have published lower/upper bounds where available. The API does
not expose bounds for rates or percentages; those remain NA and are not
derived from population. Counts are persons or years, not thousands.
Rates are age-specific or all-age crude rates as selected, not newly
age-standardized rates. Published GHE vintages can revise earlier years.
A tibble with iso3, location_name, year, sex, age,
cause_code, cause_name, measure, value, low, high,
population, unit, level, cause_group, and rankable.
A who_provenance attribute records the backend, table and retrieval.
ghe_causes(), ghe_dimensions(), ghe_coverage(), ghe_clean(), snapshot()
ghe_data(area = 'PHL', year = 2023, age = 'TOTAL', sex = 'TOTAL', cause = 0, measure = 'deaths') ghe_data(area = 'PHL', year = 2023, age = 'Y40T44', sex = c('FEMALE', 'MALE'), cause = 0, measure = 'death_rate')ghe_data(area = 'PHL', year = 2023, age = 'TOTAL', sex = 'TOTAL', cause = 0, measure = 'deaths') ghe_data(area = 'PHL', year = 2023, age = 'Y40T44', sex = c('FEMALE', 'MALE'), cause = 0, measure = 'death_rate')
Retrieves official references and small, filtered code-list slices from WHO's public xMart GHE table. Results are cached in memory for ten minutes.
ghe_dimensions(dimension = "measure")ghe_dimensions(dimension = "measure")
dimension |
One of |
A tibble of code and label. Cause results include hierarchy
fields. Measures include their provider field and unit. Missing official
labels remain NA. Countries, ages and causes describe the latest GHE
year; use ghe_coverage() to verify a specific selection.
ghe_data(), ghe_causes(), ghe_coverage()
ghe_dimensions('sex') ghe_dimensions('age') ghe_dimensions('measure')ghe_dimensions('sex') ghe_dimensions('age') ghe_dimensions('measure')
Selects, renames, and type-casts the most useful columns from a GHO
observation table returned by gho_data(), producing a compact
tibble in the unified DSIR cleaned-indicator schema — the same
schema produced by sdg_clean(), so the two outputs can be combined
directly with bind_indicators().
gho_clean(df, keep_dimensions = FALSE, keep_metadata = FALSE)gho_clean(df, keep_dimensions = FALSE, keep_metadata = FALSE)
df |
A data frame returned by |
keep_dimensions |
Logical. Append |
keep_metadata |
Logical. Retain source context? Default |
The mapping (GHO source → unified column) is:
IndicatorCode → id
IndicatorCode resolved against the GHO indicator catalog →
indicator (the human-readable name; cached at session level
after the first call)
SpatialDim → location; also iso3 when it matches a WHO
Member State, otherwise iso3 = NA
TimeDim → year (integer)
Value → value (character; raw)
NumericValue → value_num (numeric)
Low, High → low, high (numeric)
Dim1, Dim2, Dim3 → dim1, dim2, dim3 (character)
The series column is always NA for GHO output (it is an SDG-only
concept; GHE uses it for measure codes). The location_name column is populated by looking up
location (an ISO3 code or a WHO region code) against the
who_countries dataset and a hardcoded set of WHO regional names;
other locations use a published SpatialName when available, otherwise
they remain NA.
Source columns absent from df (e.g. Low / High for indicators
without confidence intervals) are filled with typed NA, so the
default output always has the same 15 columns with the same column types.
xMart supplies indicator labels through its official directory. Legacy
observations without an IndicatorName use gho_indicators() with the
backend recorded in their Provider column or who_provenance attribute,
even if the session default has changed since retrieval. Older/imported
data without provenance use the session default for this label lookup.
For such input, on the first call within an R session,
gho_clean() fetches the catalog once and caches it for the rest of
the session, so the indicator column carries the full
human-readable indicator name. If the catalog cannot be fetched
(e.g. no network), gho_indicators() emits a warning and the
indicator column falls back to NA.
A tibble with 15 core columns: source (always
"gho"), id, indicator, location, iso3, location_name,
year, value, value_num, low, high, series (NA),
dim1, dim2, dim3. Sorted by location then year.
Empty input returns an empty tibble with the same columns and
types. Optional dimension types and metadata follow the core columns.
gho_data(), sdg_clean(), bind_indicators().
gho_data("NCDMORT3070", spatial_type = "country") |> gho_clean()gho_data("NCDMORT3070", spatial_type = "country") |> gho_clean()
Sends a $top=0&$count=true request to the WHO GHO OData API,
which returns the matching row count without transferring any
observations. Useful for sizing a download before issuing it.
gho_count( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )gho_count( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )
indicator |
Character scalar. The indicator code
(e.g. |
spatial_type |
Character. Spatial dimension to filter on:
one of |
area |
Character vector of country or region codes
(e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
dim1, dim2, dim3
|
Character vector of values to keep for the
|
dimensions |
Optional named list of exact xMart dimension fields and
values, e.g. |
backend |
Character scalar. |
An integer scalar — the number of observations the
server would return for the same filter via gho_data().
Returns NA_integer_ (with a warning) if the request fails.
gho_data(), gho_has_data(), gho_coverage().
# How many rows would gho_data() pull for France? gho_count("WHOSIS_000001", area = "FRA") # Compare coverage across regions gho_count("NCDMORT3070", spatial_type = "country") gho_count("NCDMORT3070", spatial_type = "region")# How many rows would gho_data() pull for France? gho_count("WHOSIS_000001", area = "FRA") # Compare coverage across regions gho_count("NCDMORT3070", spatial_type = "country") gho_count("NCDMORT3070", spatial_type = "region")
Fetches only the SpatialDim and TimeDim columns for a GHO
indicator (much lighter than gho_data()) and summarises the
year range and observation count per location. Useful for
answering "which countries have data, and for what years?"
before committing to a full download.
gho_coverage( indicator, spatial_type = "country", area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )gho_coverage( indicator, spatial_type = "country", area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )
indicator |
Character scalar. The indicator code
(e.g. |
spatial_type |
Character. Spatial dimension to filter on:
one of |
area |
Character vector of country or region codes
(e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
dim1, dim2, dim3
|
Character vector of values to keep for the
|
dimensions |
Optional named list of exact xMart dimension fields and
values, e.g. |
backend |
Character scalar. |
A tibble with one row per location and columns:
location (chr) — the SpatialDim value (typically ISO3).
year_min (int) — earliest year with data.
year_max (int) — latest year with data.
n_obs (int) — number of observations.
Sorted by location. Empty input or service failure returns
an empty tibble with the same four columns.
gho_data(), gho_has_data(), gho_count().
# Year coverage of life expectancy for three countries gho_coverage("WHOSIS_000001", area = c("FRA", "DEU", "JPN")) # All countries with any life-expectancy data, since 2010 gho_coverage("WHOSIS_000001", year_from = 2010)# Year coverage of life expectancy for three countries gho_coverage("WHOSIS_000001", area = c("FRA", "DEU", "JPN")) # All countries with any life-expectancy data, since 2010 gho_coverage("WHOSIS_000001", year_from = 2010)
Retrieves observations for a specific indicator from the WHO GHO OData API, with optional filters by spatial level, country / region and year range.
gho_data( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )gho_data( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )
indicator |
Character scalar. The indicator code
(e.g. |
spatial_type |
Character. Spatial dimension to filter on:
one of |
area |
Character vector of country or region codes
(e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
dim1, dim2, dim3
|
Character vector of values to keep for the
|
dimensions |
Optional named list of exact xMart dimension fields and
values, e.g. |
backend |
Character scalar. |
Uses the legacy GHO OData backend by default for compatibility. Select
backend = "xmart" to use the public production WHO xMart service, or
set options(DSIR.who_backend = "xmart") as a session default.
DSIR.who_base_url selects another compatible HTTPS xMart origin. Failures never
trigger a silent fallback. Public directory coverage differs from the
legacy catalog, and published estimates can differ. Unknown xMart directory
codes warn; legacy HTTP 404 responses are checked against its directory
before being classified as absent codes. A successful query with no
matching observations emits an informational message. Request or parsing
failures warn, and do not establish that no data exist.
Reference lookups are cached only in memory; no credentials
or startup requests are required.
A tibble of indicator observations, or
an empty tibble when the service is unreachable or no observations match.
The raw Provider column records "legacy" or "xmart" per row.
A who_provenance attribute records the selected backend and, for
successful downloads, the request context and retrieval time.
gho_indicators(), gho_dimensions().
# Country-level data for one indicator gho_data("NCDMORT3070", spatial_type = "country") # Specific countries and years gho_data("WHOSIS_000001", area = c("FRA", "DEU"), year_from = 2015) # Keep only the both-sexes breakdown, filtered server-side gho_data("NCDMORT3070", spatial_type = "country", dim1 = "SEX_BTSX") # Select xMart for one call without changing the session default gho_data("NCDMORT3070", area = "PHL", year_from = 2020, year_to = 2021, dimensions = list(DIM_SEX = "TOTAL"), backend = "xmart")# Country-level data for one indicator gho_data("NCDMORT3070", spatial_type = "country") # Specific countries and years gho_data("WHOSIS_000001", area = c("FRA", "DEU"), year_from = 2015) # Keep only the both-sexes breakdown, filtered server-side gho_data("NCDMORT3070", spatial_type = "country", dim1 = "SEX_BTSX") # Select xMart for one call without changing the session default gho_data("NCDMORT3070", area = "PHL", year_from = 2020, year_to = 2021, dimensions = list(DIM_SEX = "TOTAL"), backend = "xmart")
Returns the unique values of a given dimension across all
observations of a GHO indicator. Useful for discovering which
ages, sexes, regions, or other breakdowns are available before
calling gho_data().
gho_dimensions(indicator, dimension = "SpatialDimType", backend = NULL)gho_dimensions(indicator, dimension = "SpatialDimType", backend = NULL)
indicator |
Character scalar. The indicator code
(e.g. |
dimension |
Character. Name of the dimension column in the
indicator data. Common values include |
backend |
Character scalar. |
Only the requested column is downloaded (via the OData $select
query option), so this is a lightweight metadata query even for
indicators with hundreds of thousands of observations. A
dimension that is not a column of the GHO data table (e.g. a
misspelling) makes the server reject the request; the failure
surfaces as a warning and an empty character vector.
A character vector of unique, sorted dimension values, or an empty character vector when the service is unreachable or the dimension is missing.
gho_dimensions("NCDMORT3070") gho_dimensions("NCDMORT3070", dimension = "Dim1")gho_dimensions("NCDMORT3070") gho_dimensions("NCDMORT3070", dimension = "Dim1")
Sends a minimal request ($top=1 with a row count) to the WHO GHO OData
API to find out whether any observations exist for the given
indicator and filter combination, without downloading the full
result set. Useful as a quick precheck before gho_data().
gho_has_data( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )gho_has_data( indicator, spatial_type = NULL, area = NULL, year_from = NULL, year_to = NULL, dim1 = NULL, dim2 = NULL, dim3 = NULL, dimensions = NULL, backend = NULL )
indicator |
Character scalar. The indicator code
(e.g. |
spatial_type |
Character. Spatial dimension to filter on:
one of |
area |
Character vector of country or region codes
(e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
dim1, dim2, dim3
|
Character vector of values to keep for the
|
dimensions |
Optional named list of exact xMart dimension fields and
values, e.g. |
backend |
Character scalar. |
A logical scalar:
TRUE if at least one observation exists for the filter.
FALSE if the server returns an empty result.
NA if the request fails (network failure, unreachable host,
or the indicator code does not exist and the server returns an
HTTP error). A warning is emitted in the failure case.
gho_data(), gho_count(), gho_coverage().
# Does WHO have life-expectancy data for France? gho_has_data("WHOSIS_000001", area = "FRA") # Quickly screen a list of indicators before downloading any data inds <- c("WHOSIS_000001", "NCDMORT3070") vapply(inds, gho_has_data, logical(1), area = "FRA")# Does WHO have life-expectancy data for France? gho_has_data("WHOSIS_000001", area = "FRA") # Quickly screen a list of indicators before downloading any data inds <- c("WHOSIS_000001", "NCDMORT3070") vapply(inds, gho_has_data, logical(1), area = "FRA")
Fetches the catalog of indicators from the WHO Global Health Observatory (GHO) OData API.
gho_indicators(search = NULL, backend = NULL)gho_indicators(search = NULL, backend = NULL)
search |
Optional character. Search keywords matched against
Search terms are matched literally; they are not download identifiers. |
backend |
Character scalar. |
A tibble with columns IndicatorCode,
IndicatorName and Language. Returns an empty tibble (with
a warning) when the service is unreachable.
# All indicators inds <- gho_indicators() # Single keyword gho_indicators("mortality") # Multiple keywords from one string (AND): both terms must appear gho_indicators("child mortality") # Or pass terms as a vector gho_indicators(c("child", "mortality"))# All indicators inds <- gho_indicators() # Single keyword gho_indicators("mortality") # Multiple keywords from one string (AND): both terms must appear gho_indicators("child mortality") # Or pass terms as a vector gho_indicators(c("child", "mortality"))
Maps ISO 3166-1 alpha-3 country codes to UN M49 numeric area codes
using the who_countries dataset shipped with DSIR. Useful when
moving from data sources keyed by ISO3 (e.g. the WHO GHO API) to
sources keyed by M49 (e.g. the UN SDG API).
iso3_to_m49(iso3)iso3_to_m49(iso3)
iso3 |
Character vector of ISO3 codes. Case-insensitive; values are upper-cased before lookup. |
Codes that do not correspond to a WHO Member State return NA.
This includes Associate Members (e.g. Puerto Rico) and other
non-Member areas that some indicator data sets cover.
Most users will not need to call this function directly:
sdg_data() and sdg_coverage() accept ISO3 codes for their
area argument and convert internally. This helper is exported
for cases where you want to inspect or manipulate the conversion
yourself.
A character vector the same length as iso3, with M49
codes in the same format as who_countries$m49_code (three-
character zero-padded strings, e.g. "076"). Non-Member areas
return NA.
who_countries, iso3_to_region(), sdg_data().
iso3_to_m49(c("PHL", "FRA", "JPN")) # "608" "250" "392" # Case-insensitive iso3_to_m49("phl") # "608" # Non-Member areas return NA iso3_to_m49(c("PRI", "PHL")) # NA "608"iso3_to_m49(c("PHL", "FRA", "JPN")) # "608" "250" "392" # Case-insensitive iso3_to_m49("phl") # "608" # Non-Member areas return NA iso3_to_m49(c("PRI", "PHL")) # NA "608"
Maps ISO 3166-1 alpha-3 country codes to WHO region codes using
the who_countries dataset shipped with DSIR. Stays in sync with
WHO governance changes reflected in DSIR — for example, Indonesia's
reassignment from SEAR to WPR following EB156 (May 2025).
iso3_to_region(iso3, long = FALSE)iso3_to_region(iso3, long = FALSE)
iso3 |
Character vector of ISO3 codes. Case-sensitive
(uppercase, as in |
long |
Logical. If |
Codes that do not correspond to a WHO Member State return NA.
This includes Associate Members (Puerto Rico, Tokelau) and other
non-Member areas that some indicator data sets cover.
A character vector the same length as iso3.
iso3_to_region(c("PHL", "FRA", "USA", "COK")) # "WPR" "EUR" "AMR" "WPR" iso3_to_region(c("IDN", "JPN"), long = TRUE) # "Western Pacific" "Western Pacific" (Indonesia in WPR since May 2025) # Non-Member areas return NA iso3_to_region(c("PRI", "TKL", "PHL")) # NA NA "WPR"iso3_to_region(c("PHL", "FRA", "USA", "COK")) # "WPR" "EUR" "AMR" "WPR" iso3_to_region(c("IDN", "JPN"), long = TRUE) # "Western Pacific" "Western Pacific" (Indonesia in WPR since May 2025) # Non-Member areas return NA iso3_to_region(c("PRI", "TKL", "PHL")) # NA NA "WPR"
Builds a standard period life table from age-specific mortality rates
(nMx). Works with both abridged tables (age groups 0, 1, 5, 10, ..., 85+) and complete single-year tables (0, 1, 2, ..., 100+); the last
age group is always treated as open-ended.
life_table( age, mx, sex = c("total", "male", "female"), ax = NULL, radix = 1e+05 )life_table( age, mx, sex = c("total", "male", "female"), ax = NULL, radix = 1e+05 )
age |
Numeric vector of age-group lower bounds, strictly
increasing, e.g. |
mx |
Numeric vector of age-specific mortality rates (deaths per
person-year), the same length as |
sex |
Character. |
ax |
Optional numeric vector overriding the default person-years
assumptions, the same length as |
radix |
Numeric. The starting cohort size |
The conversion from the mortality rate mx to the probability of
dying qx uses the standard relation
where is the average number of person-years lived in the
interval by those dying in it. Values of qx are capped at 1 (with a
warning, since capping signals implausibly high rates). In the open
interval, qx = 1 and Lx = lx / mx.
The ax assumption. By default:
age 0 (when the first group is age 0 with width 1): the Coale-Demeny
West formulas keyed on m0 (Preston, Heuveline and Guillot 2001,
Table 3.3), by sex. For sex = "total", the male and female
values are averaged.
ages 1-4 (when the second group is ages 1-4): the corresponding Coale-Demeny West formula.
all other closed intervals: n / 2 (the midpoint assumption).
open interval: 1 / mx (the life expectancy implied by a constant
rate).
Pass your own ax vector to override all of this, e.g. to match a
published table exactly.
Life expectancy at any tabulated age is read off the ex column:
ex[1] is life expectancy at birth when the table starts at age 0.
The table may also start above age 0 (e.g. age = c(60, 65, ..., 85))
to compute remaining life expectancy conditional on survival to the
first age.
A tibble with one row per age group and columns:
Age-group lower bound (as supplied).
Width of the age interval; Inf for the open interval.
Age-specific mortality rate (as supplied).
Average person-years lived in the interval by those dying in it.
Probability of dying in the interval; 1 in the open interval.
Survivors at exact age x out of radix.
Deaths in the interval.
Person-years lived in the interval.
Person-years lived above exact age x.
Remaining life expectancy at exact age x. NA where
lx has reached 0.
Preston SH, Heuveline P, Guillot M (2001). Demography: Measuring and Modeling Population Processes. Blackwell, Oxford. Chapter 3.
Coale AJ, Demeny P, Vaughan B (1983). Regional Model Life Tables and Stable Populations. 2nd ed. Academic Press, New York.
age_standardize() for age-standardized rates; aarr() for
indicator progress tracking.
# Abridged life table for a typical middle-income mortality schedule age <- c(0, 1, seq(5, 85, by = 5)) mx <- c(0.0200, 0.0010, 0.0004, 0.0003, 0.0005, 0.0007, 0.0009, 0.0012, 0.0016, 0.0022, 0.0032, 0.0048, 0.0075, 0.0120, 0.0190, 0.0310, 0.0520, 0.0860, 0.1500) lt <- life_table(age, mx) lt # Life expectancy at birth and at age 60 lt$ex[1] lt$ex[lt$age == 60] # Sex-specific infant ax (affects e0 slightly) life_table(age, mx, sex = "female")$ex[1] # Survivorship proportions instead of a 100,000 radix life_table(age, mx, radix = 1)$lx# Abridged life table for a typical middle-income mortality schedule age <- c(0, 1, seq(5, 85, by = 5)) mx <- c(0.0200, 0.0010, 0.0004, 0.0003, 0.0005, 0.0007, 0.0009, 0.0012, 0.0016, 0.0022, 0.0032, 0.0048, 0.0075, 0.0120, 0.0190, 0.0310, 0.0520, 0.0860, 0.1500) lt <- life_table(age, mx) lt # Life expectancy at birth and at age 60 lt$ex[1] lt$ex[lt$age == 60] # Sex-specific infant ax (affects e0 slightly) life_table(age, mx, sex = "female")$ex[1] # Survivorship proportions instead of a 100,000 radix life_table(age, mx, radix = 1)$lx
Maps UN M49 numeric area codes to ISO 3166-1 alpha-3 country codes
using the who_countries dataset shipped with DSIR. Counterpart
to iso3_to_m49() and used internally by sdg_clean() to populate
the iso3 column on SDG output.
m49_to_iso3(m49)m49_to_iso3(m49)
m49 |
Character vector of M49 codes. |
M49 codes that do not correspond to a WHO Member State return NA.
This includes region / world aggregates (e.g. "900" for World,
"001" for World, "419" for Latin America and the Caribbean)
and codes for non-Member areas (e.g. Puerto Rico, Tokelau).
Input accepts either the zero-padded form ("076") or the bare
form ("76"); both are normalised before lookup. Non-numeric
input returns NA (with a single warning from the underlying
as.integer() coercion).
A character vector the same length as m49. Non-Member
codes (region aggregates, non-Member areas) return NA.
who_countries, iso3_to_m49(), sdg_clean().
m49_to_iso3(c("608", "250", "392")) # "PHL" "FRA" "JPN" # Zero-padded and bare forms both accepted m49_to_iso3(c("076", "76")) # "BRA" "BRA" # Non-Member areas / aggregates return NA m49_to_iso3(c("900", "608")) # NA "PHL"m49_to_iso3(c("608", "250", "392")) # "PHL" "FRA" "JPN" # Zero-padded and bare forms both accepted m49_to_iso3(c("076", "76")) # "BRA" "BRA" # Non-Member areas / aggregates return NA m49_to_iso3(c("900", "608")) # NA "PHL"
Character vector of ISO3 codes for the 14 WHO Member States classified as Pacific Island Countries (PICs). Sorted alphabetically.
pic_ctypic_cty
A character vector of 14 ISO 3166-1 alpha-3 codes.
All 14 PICs are within the Western Pacific Region, so
all(pic_cty %in% wpro_cty) is TRUE. Non-Member Pacific areas
(e.g. New Caledonia, French Polynesia, American Samoa, Tokelau) are
not included.
The 14 PIC Member States are: Cook Islands, Fiji, Kiribati, Marshall Islands, Micronesia (Federated States of), Nauru, Niue, Palau, Papua New Guinea, Samoa, Solomon Islands, Tonga, Tuvalu, and Vanuatu.
length(pic_cty) # 14 all(pic_cty %in% wpro_cty) # TRUElength(pic_cty) # 14 all(pic_cty %in% wpro_cty) # TRUE
Thin wrappers around ggplot2::scale_y_continuous() and
ggplot2::scale_x_continuous() that remove the default lower expansion
so that columns sit flush with the axis — the convention for WHO and
most publication-style bar charts. The upper expansion is preserved at
5% so the tallest column has breathing room above (or to the right of) it.
scale_y_dsi_col(...) scale_x_dsi_col(...)scale_y_dsi_col(...) scale_x_dsi_col(...)
... |
Arguments forwarded to the underlying
|
Use scale_y_dsi_col() for vertical bars (geom_col() / geom_bar())
and scale_x_dsi_col() when bars are horizontal (via coord_flip() or
geom_col(orientation = "y")).
Pass any other scale_*_continuous() argument
(labels, breaks, limits, ...) through ....
A ggplot2 Scale object, to be added to a plot with +.
library(ggplot2) # Vertical bars ggplot(mtcars, aes(factor(cyl))) + geom_bar(fill = "#0093D5") + scale_y_dsi_col() + theme_dsi()library(ggplot2) # Vertical bars ggplot(mtcars, aes(factor(cyl))) + geom_bar(fill = "#0093D5") + scale_y_dsi_col() + theme_dsi()
Fetches the list of geographic areas available from the UN SDG database.
sdg_areas()sdg_areas()
A tibble with area codes and names, or
NULL when the service is unreachable.
sdg_areas()sdg_areas()
Selects, renames, and type-casts the most useful columns from an
SDG observation table returned by sdg_data(), producing a compact
tibble in the unified DSIR cleaned-indicator schema — the same
schema produced by gho_clean(), so the two outputs can be combined
directly with bind_indicators().
sdg_clean(df, keep_dimensions = FALSE, keep_metadata = FALSE)sdg_clean(df, keep_dimensions = FALSE, keep_metadata = FALSE)
df |
A data frame returned by |
keep_dimensions |
Logical. Append the named SDG dimensions as
character columns? Default |
keep_metadata |
Logical. Retain observation attributes and source
context? Default |
The mapping (SDG source → unified column) is:
indicator (list-column, flattened) → id (e.g. "3.4.1")
seriesDescription → indicator (human-readable
label; NA if the API response does not include it)
geoAreaCode → location (UN M49 numeric,
as character); also iso3 via m49_to_iso3() for WHO Member
States — region / world aggregates and non-Member areas get
iso3 = NA
location_name is resolved by looking up iso3 against
who_countries (so a WHO Member State has the same
location_name here and in gho_clean() output), with a
fallback to the SDG API's raw geoAreaName for non-Member-State
rows (e.g. regional / world aggregates)
timePeriodStart → year (integer)
value → value (character; raw)
and value_num (numeric; NA for non-numeric entries like
"<0.1" or aggregate notes)
lowerBound, upperBound → low, high (numeric)
series → series
Three columns are always present but never populated for SDG
output: dim1, dim2, dim3 (GHO-only positions). SDG uses named
dimensions, potentially more than three, with no general mapping to
those positions. Set keep_dimensions = TRUE to retain all observed
SDG dimensions as additional columns. The default compact output omits
them, so filter to the required strata before using it for analysis.
A tibble with 15 core columns: source (always
"sdg"), id, indicator, location, iso3, location_name,
year, value, value_num, low, high, series, dim1
(NA), dim2 (NA), dim3 (NA). Sorted by location then
year. Empty input returns an empty tibble with the same columns
and types. With keep_dimensions = TRUE, available named dimensions
follow the core columns, including on zero-row subsets of raw data.
With keep_metadata = TRUE, source context follows those columns.
sdg_data(), gho_clean(), bind_indicators(),
sdg_dimensions(), m49_to_iso3().
sdg_data("3.2.1", area = "156", year_from = 2015) |> sdg_clean(keep_dimensions = TRUE)sdg_data("3.2.1", area = "156", year_from = 2015) |> sdg_clean(keep_dimensions = TRUE)
A single SDG indicator (for example "3.4.1", NCD mortality) is
typically published as several series stratified by sex, age,
or cause. Different series may have different country and year
coverage. sdg_coverage() summarises year range and observation
count per (location, series) combination, so you can see which
series exist for an indicator and how each one is covered before
committing to a downstream analysis.
sdg_coverage( indicator, area = NULL, year_from = NULL, year_to = NULL, series = NULL, dimensions = NULL )sdg_coverage( indicator, area = NULL, year_from = NULL, year_to = NULL, series = NULL, dimensions = NULL )
indicator |
Character vector of SDG indicator codes
(e.g. |
area |
Character vector of country/area codes. Accepts either
ISO3 codes (e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
series, dimensions
|
Optional series codes and named dimension
filters, passed to |
Unlike the GHO availability helpers, this function is a
series-exploration tool rather than a payload-saving precheck:
SDG data is generally complete enough that GHO-style
has_data() / count() helpers add little value, so they are
intentionally not provided. The SDG API also offers no
payload-reduction option (no $select equivalent), so
sdg_coverage() calls sdg_data() internally and aggregates
the result client-side.
A tibble with one row per
(location, series) and columns:
location (chr) — area code (geoAreaCode).
series (chr) — SDG series code.
year_min (int) — earliest year with data.
year_max (int) — latest year with data.
n_obs (int) — number of observations.
Sorted by location then series. Empty input or service
failure returns an empty tibble with the same five columns. Request,
parsing, and incomplete-download warnings from sdg_data() are retained.
sdg_data(), sdg_indicators(), gho_coverage().
# Series available for NCD mortality in China and Brazil sdg_coverage("3.4.1", area = c("156", "076")) # Filter to a year range sdg_coverage("3.4.1", area = "156", year_from = 2015)# Series available for NCD mortality in China and Brazil sdg_coverage("3.4.1", area = c("156", "076")) # Filter to a year range sdg_coverage("3.4.1", area = "156", year_from = 2015)
Retrieves data for one or more SDG indicators from the UN SDG API, with optional filters by area, year, series, and named dimensions.
sdg_data( indicator, area = NULL, year_from = NULL, year_to = NULL, page_size = 1000L, series = NULL, dimensions = NULL )sdg_data( indicator, area = NULL, year_from = NULL, year_to = NULL, page_size = 1000L, series = NULL, dimensions = NULL )
indicator |
Character vector of indicator codes
(e.g. |
area |
Character vector of country/area codes. Accepts either
ISO3 codes (e.g. |
year_from |
Numeric. Start year filter (inclusive).
Default |
year_to |
Numeric. End year filter (inclusive).
Default |
page_size |
Integer. Number of records per page.
Default |
series |
Optional character vector of series codes to keep.
Default |
dimensions |
Optional named list of character vectors, using the
exact names and codes in the returned |
A tibble of indicator observations, or
an empty tibble when the service is unreachable or there are no
matching rows. The raw dimensions and attributes columns retain
the API's named breakdowns and attributes (usually packed data-frame
columns). Inspect unique(df$dimensions) to discover observed strata.
Use sdg_clean(df, keep_dimensions = TRUE) to retain named dimensions
as flat columns when cleaning. If reported page numbers, page counts,
or total row counts are inconsistent, warns and returns no rows. Counts
are checked before local filters. Counts omitted by the API cannot be
verified; a response without totalPages is treated as one page.
sdg_indicators(), sdg_areas(), sdg_clean(),
sdg_dimensions(), iso3_to_m49().
# One indicator, one country — the typical entry point sdg_data("1.1.1", area = "PHL") # Specific area and year range (M49 code) sdg_data("3.2.1", area = "156", year_from = 2015, year_to = 2023) # ISO3 codes work directly — DSIR's regional vectors can be passed in sdg_data("3.4.1", area = c("PHL", "FRA", "JPN"))# One indicator, one country — the typical entry point sdg_data("1.1.1", area = "PHL") # Specific area and year range (M49 code) sdg_data("3.2.1", area = "156", year_from = 2015, year_to = 2023) # ISO3 codes work directly — DSIR's regional vectors can be passed in sdg_data("3.4.1", area = c("PHL", "FRA", "JPN"))
Retrieves the official code lists for each series linked to an SDG
indicator, without downloading its observations. These are available
categories, not evidence that every category occurs in every country's
data. Inspect unique(df$dimensions) after sdg_data() to see observed
strata. Use the code column for filters; sdmx is an alternative
representation and may differ from the JSON API's observation codes.
sdg_dimensions(indicator, series = NULL, include_attributes = FALSE)sdg_dimensions(indicator, series = NULL, include_attributes = FALSE)
indicator |
A single SDG indicator code, e.g. |
series |
Optional character vector of series codes linked to the
indicator. Default |
include_attributes |
Logical. Also return attribute code lists,
including units and data nature? Default |
A tibble with character columns indicator, series, kind
("dimension" or "attribute"), dimension (the original field
name), code, label, and sdmx. Missing source labels stay NA.
Sorted by series, kind, dimension, and code. If any required request
fails or its structure is invalid, warns and returns a typed empty
tibble instead of a partial code list.
sdg_data(), sdg_clean(), sdg_indicators().
sdg_dimensions("3.8.2") sdg_dimensions("3.8.2", include_attributes = TRUE)sdg_dimensions("3.8.2") sdg_dimensions("3.8.2", include_attributes = TRUE)
Fetches the list of Sustainable Development Goals from the UN SDG API.
sdg_goals(include_children = FALSE)sdg_goals(include_children = FALSE)
include_children |
Logical. Include targets and indicators
nested under each goal? Default |
A list (or tibble) of SDG goals, or
NULL when the service is unreachable.
sdg_targets(), sdg_indicators(), sdg_data().
sdg_goals() sdg_goals(include_children = TRUE)sdg_goals() sdg_goals(include_children = TRUE)
Fetches the list of SDG indicators from the UN SDG API, with optional keyword filtering on the indicator description.
sdg_indicators(search = NULL)sdg_indicators(search = NULL)
search |
Optional character. Search keywords matched against
the
The filter is applied client-side using
|
A list (or tibble) of SDG indicators,
or NULL when the service is unreachable. When search matches
no rows, an empty tibble with the same columns as the unfiltered
response is returned.
# Full list sdg_indicators() # Single keyword sdg_indicators("mortality") # Multi-keyword — AND semantics sdg_indicators("mortality cancer") sdg_indicators(c("maternal", "mortality"))# Full list sdg_indicators() # Single keyword sdg_indicators("mortality") # Multi-keyword — AND semantics sdg_indicators("mortality cancer") sdg_indicators(c("maternal", "mortality"))
Fetches the list of SDG targets from the UN SDG API.
sdg_targets(include_children = FALSE)sdg_targets(include_children = FALSE)
include_children |
Logical. Include indicators nested under
each target? Default |
A list (or tibble) of SDG targets, or
NULL when the service is unreachable.
sdg_goals(), sdg_indicators().
sdg_targets()sdg_targets()
Evaluates an expression — typically an API pull such as a
gho_data() / gho_clean() pipeline — and saves the result to an
.rds file. On later calls, the saved snapshot is read back instead
of re-evaluating the expression, so analyses re-run reproducibly and
offline once the data have been fetched.
snapshot(expr, file, refresh = FALSE, max_age = Inf)snapshot(expr, file, refresh = FALSE, max_age = Inf)
expr |
An expression producing the object to snapshot. Evaluated lazily — only when no usable snapshot exists (see Details). |
file |
Path of the snapshot file (conventionally |
refresh |
Logical. Re-evaluate |
max_age |
Numeric. Maximum acceptable snapshot age in days;
an older snapshot triggers re-evaluation as if |
The decision logic is:
If file exists, refresh = FALSE, and the snapshot is younger
than max_age days, the snapshot is read and returned. expr is
not evaluated.
Otherwise expr is evaluated. A usable result (anything other
than NULL, a 0-row data frame, or an empty list) is written to
file (directories are created as needed) and returned.
An empty result — the signature of an unreachable API, since DSIR's network functions fail soft — is never written, so a failed refresh cannot destroy a good snapshot. If an older snapshot exists it is returned instead, with a warning; otherwise the empty result is returned as-is.
snapshot() deliberately does not invent file names, manage a
cache directory, or hash arguments: you choose the path, so a project
can use a fixed name (data/indicators.rds) or a dated one, and the
file is plain saveRDS() output readable without DSIR.
To force a re-fetch, pass refresh = TRUE (or delete the file).
The snapshotted object: either the value of expr or the
contents of file, per the logic above. A message states which of
the two was used.
gho_data(), sdg_data(), bind_indicators() — the
typical producers of snapshotted objects.
path <- tempfile(fileext = ".rds") # First call evaluates the expression and writes the snapshot x <- snapshot(data.frame(a = 1:3), path) # Second call reads the snapshot; the expression is not evaluated y <- snapshot(stop("not evaluated"), path) identical(x, y) # Force a refresh z <- snapshot(data.frame(a = 1:5), path, refresh = TRUE) nrow(z) unlink(path) # Typical use: pin an API pull for a reproducible report ncd <- snapshot( gho_clean(gho_data("NCDMORT3070", "country", wpro_cty)), file.path(tempdir(), "ncdmort3070.rds") )path <- tempfile(fileext = ".rds") # First call evaluates the expression and writes the snapshot x <- snapshot(data.frame(a = 1:3), path) # Second call reads the snapshot; the expression is not evaluated y <- snapshot(stop("not evaluated"), path) identical(x, y) # Force a refresh z <- snapshot(data.frame(a = 1:5), path, refresh = TRUE) nrow(z) unlink(path) # Typical use: pin an API pull for a reproducible report ncd <- snapshot( gho_clean(gho_data("NCDMORT3070", "country", wpro_cty)), file.path(tempdir(), "ncdmort3070.rds") )
A clean, modern theme tuned for WHO and global-health publications.
Removes the panel border, draws light grid lines, and uses a muted
text colour so that the data — not the chart chrome — is the visual
focus. The grid argument controls which direction(s) the grid
lines run, so the theme works equally well for vertical bars,
horizontal bars (via coord_flip()), scatter plots, and line charts.
theme_dsi( base_size = 12, base_family = "", accent = "#0093D5", grid_color = "grey92", grid = c("both", "x", "y", "none"), legend_position = "bottom" )theme_dsi( base_size = 12, base_family = "", accent = "#0093D5", grid_color = "grey92", grid = c("both", "x", "y", "none"), legend_position = "bottom" )
base_size |
Base font size in points. Default |
base_family |
Base font family. Default |
accent |
Accent colour used for axis lines and as a default for
highlight elements. Default |
grid_color |
Colour of the major grid. Default
|
grid |
Which direction(s) to draw major grid lines. One of
|
legend_position |
Position of the legend. Default |
A ggplot2 theme object.
theme_dsi_facet() for a sibling theme tuned for faceted plots.
library(ggplot2) # Default — grid in both directions, works under coord_flip() ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point(size = 3) + theme_dsi() + labs(title = "Fuel efficiency by weight", x = "Weight (1000 lbs)", y = "Miles per gallon", color = "Cylinders") # Minimal look — only horizontal grid lines ggplot(mtcars, aes(wt, mpg)) + geom_point(size = 3, color = "#0093D5") + theme_dsi(grid = "y") + labs(x = "Weight (1000 lbs)", y = "Miles per gallon")library(ggplot2) # Default — grid in both directions, works under coord_flip() ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point(size = 3) + theme_dsi() + labs(title = "Fuel efficiency by weight", x = "Weight (1000 lbs)", y = "Miles per gallon", color = "Cylinders") # Minimal look — only horizontal grid lines ggplot(mtcars, aes(wt, mpg)) + geom_point(size = 3, color = "#0093D5") + theme_dsi(grid = "y") + labs(x = "Weight (1000 lbs)", y = "Miles per gallon")
A sibling of theme_dsi() tuned for faceted plots. Where theme_dsi()
uses half-frame axis lines and only horizontal grid lines — a look that
suits a single panel — repeating those across every facet looks heavy
and the panels run together. theme_dsi_facet() replaces the axis
lines with a light panel border, draws grid lines on both axes, gives
the strip a soft background, and inserts whitespace between panels.
theme_dsi_facet( base_size = 12, base_family = "", accent = "#0093D5", grid_color = "grey92", strip_fill = "grey95", strip_color = "grey20", grid = c("both", "x", "y", "none"), legend_position = "bottom" )theme_dsi_facet( base_size = 12, base_family = "", accent = "#0093D5", grid_color = "grey92", strip_fill = "grey95", strip_color = "grey20", grid = c("both", "x", "y", "none"), legend_position = "bottom" )
base_size |
Base font size in points. Default |
base_family |
Base font family. Default |
accent |
Accent colour, kept for parity with |
grid_color |
Colour of the major grid (both axes). Default
|
strip_fill |
Background fill colour for facet strips. Default
|
strip_color |
Text colour inside facet strips. Default |
grid |
Which direction(s) to draw major grid lines. One of
|
legend_position |
Position of the legend. Default |
Use theme_dsi() for single-panel plots and theme_dsi_facet() for
plots with facet_wrap() or facet_grid(). Shared elements (text
styles, title block, legend, plot margins) match theme_dsi() exactly,
so the two themes feel like the same family.
A ggplot2 theme object.
theme_dsi() for the single-panel sibling.
library(ggplot2) ggplot(mtcars, aes(wt, mpg)) + geom_point(size = 2, color = "#0093D5") + facet_wrap(~ cyl, labeller = label_both) + theme_dsi_facet() + labs(title = "Fuel efficiency by cylinder count", x = "Weight (1000 lbs)", y = "Miles per gallon")library(ggplot2) ggplot(mtcars, aes(wt, mpg)) + geom_point(size = 2, color = "#0093D5") + facet_wrap(~ cyl, labeller = label_both) + theme_dsi_facet() + labs(title = "Fuel efficiency by cylinder count", x = "Weight (1000 lbs)", y = "Miles per gallon")
A tibble of the 194 World Health Organization (WHO) Member States, with standard country identifiers and WHO/Pacific groupings used across DSIR analytical workflows.
who_countrieswho_countries
A tibble with 194 rows and 8 columns:
ISO 3166-1 alpha-3 code (3-letter, e.g. "PHL").
ISO 3166-1 alpha-2 code (2-letter, e.g. "PH").
UN M49 numeric code, stored as a 3-character string with
leading zeros where present (e.g. "008" for Albania). Stored as
character because some downstream APIs (notably the UN SDG API) expect
the leading-zero form.
WHO official English name (e.g.
"Iran (Islamic Republic of)"). Use for formal documents and reports.
A shorter form suitable for charts and tables (e.g.
"Iran"). Equal to name_official for countries whose official name
is already concise. See Details.
WHO region code: one of "AFR", "AMR", "SEAR",
"EUR", "EMR", "WPR".
Logical. TRUE for the 14 Pacific Island Country (PIC)
Member States in WPR, FALSE otherwise.
World Bank income classification: "High income", "Upper middle income", "Lower middle income", or "Low income". NA for Cook Islands and Niue, which are not World Bank
economies. See Details for the vintage.
Scope. WHO has 194 Member States plus 2 Associate Members (Puerto Rico, Tokelau) and reports on additional non-Member areas (e.g. West Bank and Gaza Strip). This dataset includes only the 194 Member States. Cook Islands and Niue are full WHO Member States and are included even though they are not UN member states.
Region coverage (as of May 2025, after WHO EB156 reassignment of Indonesia from SEAR to WPR):
AFR (African Region): 47
AMR (Region of the Americas): 35
SEAR (South-East Asia Region): 10
EUR (European Region): 53
EMR (Eastern Mediterranean Region): 21
WPR (Western Pacific Region): 28
Short names. name_short differs from name_official for 13
countries where the official name is a parenthetical descriptor or is
otherwise long. Examples: "DPR Korea", "DR Congo", "Lao PDR",
"United Kingdom". These short forms follow conventions used in WHO
regional reports and OECD Health at a Glance: Asia/Pacific.
PICs. The Pacific Island Countries flag (is_pic) marks the 14
WHO Member States in the Pacific sub-region: Cook Islands, Fiji,
Kiribati, Marshall Islands, Micronesia (Federated States of), Nauru,
Niue, Palau, Papua New Guinea, Samoa, Solomon Islands, Tonga, Tuvalu,
and Vanuatu. Non-Member Pacific areas (e.g. New Caledonia, French
Polynesia, American Samoa) are not included in this dataset.
Income groups. wb_income_group carries the World Bank
classification of fiscal year 2027 (released 1 July 2026; based on
2025 GNI per capita, Atlas method). The classification is revised
every 1 July, so this column reflects the vintage current at the
package release date — for a historical vintage (e.g. reproducing an
older analysis), join your own copy of the World Bank OGHIST table
instead. Cook Islands and Niue are WHO Member States but not World
Bank economies and are NA.
WHO official region listing: https://www.who.int/countries
ISO 3166-1 codes and UN M49 numeric codes: UN Statistics Division https://unstats.un.org/unsd/methodology/m49/
World Bank income classification (FY2027): https://datahelpdesk.worldbank.org/knowledgebase/articles/906519
# All WPR Member States, sorted alphabetically by short name wpr <- who_countries[who_countries$who_region == "WPR", ] wpr <- wpr[order(wpr$name_short), c("iso3", "name_short")] head(wpr) # Filter a data frame to PIC member states # df_pic <- subset(my_data, country_iso3 %in% who_countries$iso3[who_countries$is_pic]) # Income-group composition of each WHO region table(who_countries$who_region, who_countries$wb_income_group)# All WPR Member States, sorted alphabetically by short name wpr <- who_countries[who_countries$who_region == "WPR", ] wpr <- wpr[order(wpr$name_short), c("iso3", "name_short")] head(wpr) # Filter a data frame to PIC member states # df_pic <- subset(my_data, country_iso3 %in% who_countries$iso3[who_countries$is_pic]) # Income-group composition of each WHO region table(who_countries$who_region, who_countries$wb_income_group)
Convenience character vectors of ISO3 codes for the WHO Member States
in each region. Each vector is the regional subset of
who_countries's iso3 column, sorted alphabetically.
afro_cty amro_cty searo_cty euro_cty emro_cty wpro_ctyafro_cty amro_cty searo_cty euro_cty emro_cty wpro_cty
Character vectors of ISO 3166-1 alpha-3 codes.
An object of class character of length 47.
An object of class character of length 35.
An object of class character of length 10.
An object of class character of length 53.
An object of class character of length 21.
An object of class character of length 28.
These are derived directly from who_countries and exist for
ergonomic filtering, e.g.
dplyr::filter(data, iso3 %in% wpro_cty).
If you need to update group membership, edit
data-raw/who_countries.R and re-run that script — the vectors
regenerate from the master table.
afro_cty47 Member States in the WHO African Region.
amro_cty35 Member States in the WHO Region of the Americas.
searo_cty10 Member States in the WHO South-East Asia Region.
euro_cty53 Member States in the WHO European Region.
emro_cty21 Member States in the WHO Eastern Mediterranean Region.
wpro_cty28 Member States in the WHO Western Pacific Region. Includes Indonesia from May 2025 (per WHO EB156).
length(wpro_cty) # 28 "IDN" %in% wpro_cty # TRUE — Indonesia in WPR since May 2025length(wpro_cty) # 28 "IDN" %in% wpro_cty # TRUE — Indonesia in WPR since May 2025
Beginning with DSIR 0.11.0, who_std_pop uses the WHO 2026 Standard
Population, based on projected world population during 2026-2050.
who_std_popwho_std_pop
A tibble with 18 rows: five-year groups 0-4 to 80-84,
followed by 85+, and four columns:
Character age-group label.
Integer lower bound in years.
Percentage normalized to sum to 100. WHO's rounded published values sum to 100.02: divide each by 100.02 and multiply by 100.
Numeric weight scaled to sum to 1,000,000, without integer rounding. Derived counts, not separately published WHO counts.
Aggregate weights by summation for coarser age groups. Both weight
columns give identical standardized rates. The published table does
not split 0-4 or 85+: aggregate finer observed ages to these groups.
The four column names are retained; the dataset now has 18 rather than
21 rows and std_million is numeric rather than integer.
World Health Organization (2026). Revised WHO standard population for calculating age-standardized rates. WHO/HSA/DDA/GHE/2026.4, Table 1, page 6. Accessed 2026-10-06. https://cdn.who.int/media/docs/default-source/gho-documents/global-health-estimates/ghe2023_who_standard_population.pdf
who_std_pop grp <- cut(who_std_pop$age_start, c(0, 25, 65, Inf), right = FALSE, labels = c('0-24', '25-64', '65+')) tapply(who_std_pop$std_million, grp, sum)who_std_pop grp <- cut(who_std_pop$age_start, c(0, 25, 65, Inf), right = FALSE, labels = c('0-24', '25-64', '65+')) tapply(who_std_pop$std_million, grp, sum)