dimensions adds exact named filters.
The public xMart directory covers a different set of codes and vintages
than the legacy catalog. Unknown codes warn; no automatic fallback occurs.backend = "legacy" or "xmart".
An explicit argument overrides DSIR.who_backend for that call without
changing the option; an unset option defaults to legacy. GHE always uses
xMart. DSIR.who_base_url accepts a compatible HTTPS xMart origin. Reference caches
are session-only, expire after ten minutes and are scoped to provider/host./$query
POST endpoint. Compact list filters and batched dimension discovery respect
the production query limits. A source-row limit prevents accidental bulk pulls.gho_clean(keep_dimensions = TRUE) retains named xMart dimensions in
addition to dimension types. Metadata retention adds units, measure fields
and a row-level provider column. Both GHO backends record retrieval
provenance; cleaning resolves missing labels with the recorded provider,
even after the session default changes. Unknown imported origins stay NA.
The default remains the unified 15-column core.ghe_data(), ghe_causes(), ghe_dimensions(), ghe_coverage() and
ghe_clean(), using DEX_CMS/GHE_FULL. Exact geography, year, sex, age,
cause and friendly measure filters preserve uncertainty bounds and hierarchy.
Cause grouping is not presented as a parent identifier. Rates do not invent
uncertainty bounds. Named context can be retained when binding cleaned data.who_std_pop uses the WHO 2026 Standard
Population (WHO/HSA/DDA/GHE/2026.4, Table 1). Its 18 groups run from 0-4
to 85+. Published percentages sum to 100.02 and are explicitly normalized
to 100; the derived standard million sums to 1,000,000 without integer
rounding. The four column names remain, but std_million is now numeric.
No old population object is retained. Align input ages before standardizing.New sdg_dimensions() retrieves official series-specific dimension
codes and labels without downloading observations. Optional attribute
code lists include units and data nature. JSON API codes and SDMX codes
are reported separately.
gho_clean() gains keep_dimensions = TRUE, retaining dim1_type,
dim2_type, and dim3_type from each observation's source fields.
Types are not inferred from codes or assumed constant across rows.
Both cleaners gain keep_metadata = TRUE. SDG output retains all
observation attributes (as attr_* columns), source and time context,
plus all footnotes and linked indicator/goal/target codes. GHO output
retains observation identifiers, source codes, location/time context,
update timestamps, and comments. Notes and multiple codes use list-
columns. The 15-column default remains unchanged.
sdg_clean() gains keep_dimensions = TRUE to retain named SDG
breakdowns as additional character columns (dim_age, dim_sex,
dim_quantile, etc.). Previously the cleaner discarded all SDG
dimensions. The default remains the 15-column schema, and dim1
through dim3 remain GHO-only positions. No cross-source mapping
or missing category is inferred.
sdg_data() gains series and dimensions filters, applied
client-side after all pages have been retrieved. Dimension filters
use exact UN field names and codes. Missing requested dimensions
warn and return no rows rather than ignoring the restriction.
sdg_coverage() accepts series and dimensions filters, calculating
coverage for the selected observations.
sdg_data() now checks declared page numbers, page counts, and total
row counts before applying local filters. An unexpected empty page,
changing counts, or an incompatible page schema warns and returns no
rows rather than exposing a partial download as complete.
sdg_coverage() no longer suppresses request, parsing, or incomplete-
download warnings, and warns when required coverage fields are missing.
bind_indicators() preserves additional columns and fills missing
fields when binding inputs with different named dimensions.
Previously every column outside the 15-column core was dropped.
New age_standardize(): the directly age-standardized rate, with an
optional Fay-Feuer gamma confidence interval. Standard-population
weights may be supplied as counts, a standard million, or percentages
— they are normalised internally.
New dataset who_std_pop for direct age standardization. Its weights
and age groups are replaced by the WHO 2026 standard in version 0.11.0.
New life_table(): a period life table (qx, lx, dx, Lx, Tx, ex) from
age-specific mortality rates. Handles abridged and complete tables and
an open final interval, with Coale-Demeny West infant and child ax
by sex (overridable). Life expectancy at birth is ex[1].
New snapshot(): evaluate an expression (typically a gho_data() /
gho_clean() pull) once, save the result to an .rds file, and read
it back on later runs so analyses re-run reproducibly and offline. An
empty result — the signature of an unreachable API — is never written,
so a failed refresh cannot destroy a good snapshot.
who_countries gains a wb_income_group column: the World Bank income
classification (fiscal year 2027; 2025 GNI per capita, Atlas method).
Cook Islands and Niue are NA as they are not World Bank economies.
sdg_data() — and therefore sdg_coverage() — no longer errors when a
pull spans multiple pages whose nested dimensions / attributes
columns differ, which is the signature of a multi-series indicator
(each series is stratified by its own dimension set). Pages are now
combined with vctrs::vec_rbind(), which takes the union of the
nested columns and fills the cells missing from a page with NA,
where base rbind() failed with duplicate 'row.names' are not allowed after a provided k variables to replace 1 variables
warning.
GHO and SDG requests now retry on connection-level failures (timeouts,
connection resets) and on transient server errors (HTTP 500 / 502 /
504, alongside the 429 / 503 httr2 defaults). Previously only 429
and 503 were retried, so a single network hiccup — the typical symptom
of GHO API instability — failed the whole download despite the
configured max_tries = 3. The per-request timeout is also raised
from 20 to 30 seconds. Requires httr2 (>= 1.0.0).
sdg_coverage() no longer errors on rows with a missing series code:
the per-group location/series values are read back from the data
instead of re-parsed out of the internal grouping key, and a genuine
NA series stays NA rather than becoming the string "NA".
New aarr(): the average annual rate of reduction, the standard
WHO / UNICEF metric for tracking progress in declining indicators
(maternal / child mortality, premature NCD mortality, stunting).
The default "regression" method fits an OLS line to log(value)
against year and returns 1 - exp(slope) (the UNICEF-recommended
approach); an "endpoint" method using only the earliest and latest
years is also available. Positive values mean the indicator is
declining; the result is a fraction (multiply by 100 to compare with
published tables). Duplicated years — the signature of data still
mixed across strata (dim1, series) — trigger a warning.
gho_data(), gho_has_data(), gho_count(), and gho_coverage()
gain dim1 / dim2 / dim3 arguments to filter GHO breakdown
dimensions (sex, age group, ...) server-side, e.g.
gho_data("NCDMORT3070", dim1 = "SEX_BTSX"). Previously the full
observation table had to be downloaded and filtered locally. Use
gho_dimensions() to discover the values available for an
indicator.
New vignette vignette("visualizing-indicators"): ggplot2 recipes
for the cleaned-indicator schema — confidence-interval ribbons,
breakdown facets, forest-style country comparisons, dumbbell
progress plots, and progress tracking with aarr().
gho_dimensions() now downloads only the requested column (via the
OData $select query option) instead of the full observation table,
making it a lightweight metadata query even for indicators with
hundreds of thousands of rows. As a side effect, a misspelled
dimension name now surfaces a warning (the server rejects the
request) instead of silently returning an empty vector after a full
download.gho_clean() call happened while
offline, the empty catalog was cached and the indicator column
stayed NA for the rest of the session even after connectivity
returned; the catalog fetch is now retried on the next call.gho_clean() and sdg_clean() now share a single 15-column output
schema: source, id, indicator, location, iso3,
location_name, year, value, value_num, low, high,
series, dim1, dim2, dim3. This lets results from the two
APIs be combined directly (see bind_indicators() below). Migration
notes from 0.6.x:
gho_clean() output no longer has 11 columns; it has 15. New
columns include source ("gho"), iso3 (the ISO3 alpha-3
code when the spatial dim matches a WHO Member State, NA
otherwise), location_name (resolved against who_countries
and WHO regional codes; see the bug-fix note below), and
series (always NA — an SDG-only concept).sdg_clean() output no longer has 10 columns and is reshaped
to the unified schema. Several columns moved or were renamed:
the SDG goal and target columns are no longer carried
forward; the SDG indicator code is now in id (was
indicator); the human-readable series description has moved
to indicator (was not present before); a new iso3 column
holds the ISO3 alpha-3 code via m49_to_iso3() for Member
States.value_num / low / high to
numeric; non-numeric raw values (e.g. SDG "<0.1") yield NA
in those columns while value keeps the raw character form.year to integer.New bind_indicators(...): stacks any number of tibbles returned by
gho_clean() and sdg_clean() into a single tibble. Because the
two cleaners now share a schema, the result is uniform and can be
filtered, joined, or visualised without source-specific code paths;
use the source column to distinguish GHO from SDG rows.
New m49_to_iso3(): maps UN M49 numeric area codes to ISO3 country
codes, the counterpart to iso3_to_m49(). Accepts zero-padded
("076") and bare ("76") input. Non-Member areas — including
region / world aggregates — return NA. Used internally by
sdg_clean() to populate the new iso3 column.
Fixed a duplicate definition of sdg_coverage(): the function was
defined in both R/sdg.R and R/sdg_coverage.R, and R's
alphabetical source-file loading meant the wrong copy (with a
fragile \r composite-key separator and no upfront .resolve_area()
call) was the one actually in effect. The surviving implementation
now uses \x1f as the composite-key separator and resolves the
area argument up-front, so the documented "unknown ISO3 codes
warn and are dropped" message surfaces cleanly from sdg_coverage()
rather than being swallowed inside an internal call to sdg_data().
.gho_get() now sets a 20-second per-request timeout and applies
the same exponential backoff (backoff = ~ min(2 ^ .x, 30)) as
.sdg_get(). Previously a hung upstream request could stall an
entire gho_data() call indefinitely.
Network helpers now also fail soft on malformed response bodies.
.gho_get(), .sdg_get(), and the inline call in gho_count()
wrap httr2::resp_body_json() in tryCatch(), so a truncated
upstream response (premature EOF) surfaces a warning and returns
NULL / NA_integer_ instead of propagating a parse error to the
caller. Previously such a response could halt an R CMD check
example run, e.g. sdg_goals(include_children = TRUE) against a
flaky UN endpoint.
gho_clean() and sdg_clean() now populate location_name
consistently across both APIs. WHO Member States are resolved
against who_countries$name_short in both cleaners, so the same
country has the same location_name regardless of source.
gho_clean() additionally resolves the WHO regional codes
(AFR, AMR, SEAR, EUR, EMR, WPR) and GLOBAL to their
human-readable names. sdg_clean() falls back to the SDG API's
original geoAreaName for non-Member-State rows (e.g. regional
and world aggregates), preserving information that who_countries
does not carry.
gho_clean() now actually populates the indicator column. The
GHO data endpoint (/api/{IndicatorCode}) does not return
IndicatorName, so the old implementation left indicator NA
for every row despite the documented mapping. gho_clean() now
lazy-loads the indicator catalog (via gho_indicators()) once per
R session and resolves IndicatorCode against it to fill the
indicator column with the human-readable name. The output
schema is unchanged; if the catalog cannot be fetched, indicator
falls back to NA and a warning surfaces from gho_indicators().
\donttest{} instead of \dontrun{},
so CRAN reviewers can opt to run them.Added httptest2 to Suggests. The GHO and SDG helpers gain offline
regression tests covering the empty value=[] fix, the OData
pagination loop, the multi-value SDG indicator / areaCode
repeated-key URL form, the client-side SDG year filter, and the
graceful-failure behaviour on HTTP errors.
Test coverage expanded for gho_clean(), sdg_clean(),
bind_indicators(), m49_to_iso3(), scale_*_dsi_col(), the
who_countries dataset, and the regional ISO3 vectors.
theme_dsi() now draws grid lines in both directions by default. New
grid argument controls direction — pass grid = "y" to restore the
previous look (horizontal grid only). This change fixes the visual
glitch where horizontal bar charts (made with coord_flip()) had grid
lines running parallel to the bars instead of crossing them.
theme_dsi_facet() gains a grid argument mirroring theme_dsi()'s —
defaults to "both" (unchanged behaviour); pass "y", "x", or
"none" to control which direction(s) the grid runs.
New scale_y_dsi_col() and scale_x_dsi_col() — drop-in replacements
for scale_y_continuous() / scale_x_continuous() that remove the
lower axis expansion, so columns in bar charts sit flush with the
axis (WHO publication style).
New theme_dsi_facet() for faceted plots — uses panel borders,
light-grey strip backgrounds, and bilateral grid lines.
New GHO data-availability helpers, for screening indicator / filter combinations before pulling a full result set:
gho_has_data() returns TRUE / FALSE / NA for whether
the server has any rows for an indicator and filter.gho_count() returns the row count the same filter would
yield, using the OData $count=true endpoint (no rows
transferred).gho_coverage() returns a tibble with location, year_min,
year_max, n_obs per area, using $select=SpatialDim,TimeDim
to keep the payload small.sdg_indicators() gains a search parameter, mirroring
gho_indicators(search). Accepts either a single string (split on
whitespace into terms) or a character vector (terms used verbatim).
All terms must match (AND semantics, case-insensitive substring on
the indicator description column). The filter is applied
client-side because the UN SDG /Indicator/List endpoint is not
OData and exposes no server-side search parameter; the list is
small enough (~250 rows) that this is cheap.
New sdg_coverage(): series-exploration helper for SDG indicators.
An SDG indicator (e.g. "3.4.1") typically contains several series
stratified by sex, age, or cause; sdg_coverage() returns a tibble
of (location, series, year_min, year_max, n_obs) so you can see
which series exist and how each is covered. This is intentionally
framed as series-exploration rather than as a gho_has_data() /
gho_count()-style availability precheck — SDG data is generally
complete, so those screening helpers are deliberately not provided
for SDG.
New geomean(): geometric mean of a numeric vector, with optional
weights via w. Useful for aggregating ratio-based health
indicators such as UHC service-coverage tracers. Handles NA
(removed by default), zeros (returns 0), and negative values
(warns and returns NaN).
New iso3_to_m49(): maps ISO3 country codes to UN M49 numeric
codes using the bundled who_countries dataset. Non-Member codes
return NA. Input is case-insensitive.
sdg_data() and sdg_coverage() now accept ISO3 codes directly
for the area argument; M49 codes continue to work unchanged.
DSIR's regional vectors (wpro_cty, afro_cty, etc.) can now be
passed directly to SDG functions, matching the existing GHO
workflow. ISO3 and M49 cannot be mixed within a single call.
New iso3_to_region(): maps ISO3 country codes to WHO region codes
("AFR", "AMR", "SEAR", "EUR", "EMR", "WPR") using the
bundled who_countries dataset. Pass long = TRUE for full names
("Western Pacific", etc.). Non-Member codes (e.g. Associate Members
like "PRI") return NA. Stays in sync with WHO governance changes
reflected in DSIR — e.g. Indonesia in WPR since EB156 (May 2025).
sdg_data(): year filtering (year_from / year_to) is now
applied client-side. The UN SDG API's server-side
timePeriodStart / timePeriodEnd parameters were causing
HTTP 500 errors and ~30x slowdowns on at least some
indicator/area combinations (e.g. 3.2.1 with area = "608");
client-side filtering avoids the issue. User-facing behaviour is
unchanged. sdg_coverage() inherits the fix automatically because
it dispatches through sdg_data().
.sdg_get() now sets a 20-second per-request timeout and
exponential backoff between retries (backoff = ~ min(2^.x, 30)),
so a hung upstream request cannot stall a call indefinitely.
The internal pagination helper .gho_get() previously produced a
spurious 1-row, 1-column tibble (V1 of type list) when the
server returned an empty result set (value = []). Empty value
chunks are now skipped and an empty tibble is returned when no
rows accumulate. This affected gho_data() on filters with no
matches (e.g. an indicator + area combination GHO has no data for)
and gho_indicators(search) when no indicator name matched the
search term.
sdg_data() now correctly filters when more than one indicator
or area code is supplied. The SDG API expects multi-value
parameters as repeated keys (indicator=A&indicator=B), but the
previous implementation joined them with commas
(indicator=A,B); the API silently dropped the filter and
returned all rows. Single-value calls were unaffected.
sdg_data() no longer errors with duplicate 'row.names' are not allowed when the result spans more than one page. The
per-page row-name handling has been simplified.
theme_dsi(): removed the color argument and added accent instead.
The semantics are different: color previously controlled text colour,
while accent now controls axis line and tick colour. If you used
theme_dsi(color = X) in 0.2.x, change to theme_dsi(accent = X) and
note that the visual effect has shifted from "everywhere" to "axis
only". Text colour is now fixed to grey20 to follow modern
publication conventions.gho_data() now correctly handles long area vectors. Previously,
passing more than ~22 ISO3 codes hit the upstream query string length
limit and resulted in HTTP 400 errors. Switched from chained OR clauses
to the OData in operator, which generates a much shorter URL and
supports up to ~115 codes per call.New gho_clean(): post-processor for gho_data() output. Selects
the useful columns and renames them to snake_case (id, location, year,
dim1-dim3, value, value_num, low, high, indicator). Output
schema is stable across indicators — missing columns are filled
with NA. See ?gho_clean for details.
New sdg_clean(): counterpart for sdg_data(). Renames the
SDG API columns to snake_case and flattens the indicator
list-column. Returns value, low, and high as character to
preserve non-numeric entries ("<0.1", aggregate notes); coerce
with as.numeric() downstream. See ?sdg_clean for details.
theme_dsi() redesigned to follow modern publication conventions
(BBC, OECD, Financial Times style):
grey92, was grey85)grey20legend_position argumentgho_data() now infers spatial_type = "country" when area is
provided without an explicit spatial_type. Pass spatial_type
explicitly to silence the message.
gho_data() now validates the area argument: must be a non-NA,
non-empty character vector.
New who_countries dataset: a tibble of all 194 WHO Member States with
ISO3, ISO2, UN M49 numeric code, official and short names, WHO region,
and a is_pic flag for the 14 Pacific Island Country Member States.
New regional ISO3 character vectors for ergonomic filtering:
afro_cty, amro_cty, searo_cty, euro_cty, emro_cty, plus
pic_cty. All are derived from who_countries and stay consistent
with the master table.
wpro_cty now contains 28 countries (was 22 in 0.2.0). This
reflects the May 2025 World Health Assembly decision (EB156) reassigning
Indonesia from the South-East Asia Region to the Western Pacific Region,
along with Cook Islands and Niue, which are full WHO Member States but
were previously omitted. Code that aggregates over wpro_cty (sums,
counts, joins) will produce different results than under DSIR 0.2.x —
this is intended.data-raw/who_countries.R as the single source of truth for all
country-related datasets. Editing one file regenerates the master tibble
and all derived vectors.Initial CRAN submission. Renamed from DSI to avoid a name clash
with the existing CRAN DSI package.
gho_dimensions() returns the unique values of a dimension
column for a given GHO indicator, to make it easier to discover
which breakdowns (sex, age, region, etc.) are available before
calling gho_data().sdg_targets() lists Sustainable Development Goal targets from
the UN SDG API, complementing sdg_goals() and
sdg_indicators().theme_dsi() and dsi_flextable_defaults() now default to the
device / package default font (base_family = ""), so they work
on systems where Cambria is not installed. Pass
base_family = "Cambria" to get the original look.ggpie() gains input validation and uses tidy-evaluation
helpers internally, so R CMD check no longer reports
undefined global variables.gho_*() and sdg_*() now fail gracefully when the remote
service is unreachable, per CRAN policy for packages that hit
the network. They warn and return an empty data frame (or
NULL) instead of raising a hard error.roxygen2 help pages for every exported function, with
cross-references between related functions.\donttest{} (not \dontrun{}) for
network-dependent code, so CRAN reviewers can opt into running
them.