Mongolian 'NSO' 'PXWeb' Data and Boundaries (Tidy Client)
Overview
A 'tidyverse'-friendly client for the National Statistics Office of Mongolia 'PXWeb' API https://data.1212.mn/ with helpers to discover tables, variables, and fetch statistical data. Also includes utilities to retrieve Mongolia administrative boundaries (ADM0-ADM2) as 'sf' objects from open sources for mapping and spatial analysis.
Breaking changes
- **Stricter selection validation**:
nso_data(),nso_package(),nso_query(), andas_px_query()now error when a selection name does not match any dimension in the table (previously the selection was silently ignored and the full dimension was fetched), when selections are unnamed, or when two selections target the same dimension. This prevents silently fetching wrong-scope data. Errors carry classmongolstats_selection_error.
New features
- **
nso_package()no longer fails silently**: tables that fail to fetch are reported in a warning naming each table, and a newstrict = TRUEargument raises an error instead. Previously failed tables were dropped without any signal. - **Unified
labelsvocabulary**:nso_data()andnso_package()accept"code"as an alias for"none", andnso_fetch()andnso_dim_values()accept"none"as an alias for"code", so either spelling works everywhere. - **
mn_boundaries()session cache**: boundary downloads are cached in memory for the session (repeated calls, including viamn_join_by_name(), no longer re-download multi-megabyte GeoJSON). Arefresh = TRUEargument bypasses the cache. - **
nso_period_seq()input validation**: malformed periods (wrong width, month 13,NA, vectors) and reversed ranges now error with a clear message instead of silently returning a descending sequence or failing insideseq.Date().
Bug fixes
- Ambiguous table ids now warn: the NSO catalogue can reuse one table id for different tables in different folders (e.g.
DT_NSO_2400_015V1currently names both the monthly SO2 station table and an annual air-quality-standards table). mongolstats now warns (classmongolstats_ambiguous_table) and names the folder it picked instead of silently resolving to an arbitrary table. Tables that are merely cross-listed in several folders under the same name resolve silently. - The embedded PXWeb table index has been refreshed to match the current NSO catalogue. Several tables (e.g. cancer incidence
DT_NSO_2100_012V1and communicable diseasesDT_NSO_2100_035V1) moved to different catalogue folders, which made lookups through the stale index return empty results. - **
labels = "mn"andlabels = "both"now actually attach Mongolian labels**: label metadata was matched to data columns by display text, but the two languages only share the dimension *code* (the English column is "Sex" while both languages use the code "Хүйс"), so cross-language labels were silently never added. Labels are now routed through a code-to-column map, which also fixes English labels whenmongolstats.lang = "mn". - **Offline mode no longer fires the session-cookie GET**:
.px_session_cookie()bypassed the offline gate, sonso_data()with cached metadata still performed one live request in offline mode.
Show all changes in 0.2.0Hide the rest of the changes in 0.2.0
- **Retries no longer crash on the first backoff**: the default retry backoff formula referenced
..attempt, which does not exist in rlang lambdas (the argument is.x), so any transient response (429/503) failed with "object '..attempt' not found" instead of retrying. - **HTTP error and verbose messages now include the request URL**: an internal misuse of
httr2::req_url()as a getter meant the URL always rendered asNAand was dropped from messages. - **Time columns typed
"t"are handled**: the PXWeb response flattener kept only"d"-typed columns; a server typing its time column"t"(the PXWeb convention; NSO currently uses"d") would have misaligned row keys with column names. - **
nso_fetch()now honors themongolstats.default_labelsoption**, matchingnso_data(). - **
nso_itms_search()matches its query literally** as documented ("keyword"); regex metacharacters (e.g."c++") no longer error.nso_search()remains a regex search. - **
nso_period_seq()rejects trailing garbage** after a valid year (e.g."2024abc","2024-06"); previously the year prefix was silently used. - **
mn_join_by_name()andmn_fuzzy_join_by_name()error clearly** whenname_colis not a column ofdata, instead of failing with an obscure replacement-length error. - **
nso_table_periods()finds the time dimension forlang = "mn"** by also matching the Mongolian display name. - **Mixed codes and labels**: Selection values are now mapped element-wise, so codes and labels can be mixed in one vector (e.g.
Sex = c("Total", "1")). Previously this produced an "Unknown value: NA" error. Duplicated labels in table metadata now produce a warning naming the ambiguous label. - **Consistent errors**:
as_px_query()now raises the same classed errors asnso_data()for invalid selections (previously a plainstop()). - **Correct error classes**: network failures (DNS, timeout) now signal
mongolstats_http_error; previously they were misclassified asmongolstats_offline_error, so handlers could not tell offline mode from a genuine connection problem.
Performance
- The PXWeb session cookie is now seeded once per base URL per session instead of once per data fetch, removing one GET round trip from every
nso_data()call after the first. mn_fuzzy_join_by_name()no longer computes a base-R distance matrix that was immediately discarded when stringdist is installed.
CRAN compliance
- The cache test no longer writes to (or clears) the user's real cache directory: it now skips when the cache packages are missing and uses a throwaway directory under
tempdir(). Previously it ran on CRAN and touchedrappdirs::user_cache_dir("mongolstats"). - The
nso_cache_enable()example is now conditional on memoise/cachem/rappdirs being installed. - Network-dependent examples are now guarded with
NOT_CRANin addition tocurl::has_internet(), so they no longer contact the live PXWeb API during CRAN checks. Thenso_rebuild_px_index()example, which crawls the full catalogue, is wrapped in\dontrun{}. inst/extdata/air_monthly_cached.csvis now gzip-compressed (6.4 Mb to 0.3 Mb), bringing the installed package size well under CRAN's threshold.read.csv()decompresses it transparently; only the vignette referenced it.
Internal
- Removed the unused legacy HTTP layer (
.nso_req(),.nso_get(),.nso_post()and friends) together with the now-inertmongolstats.base_urloption; all requests go to the PXWeb API base (mongolstats.px_base_url). nso_search()andnso_itms_search()share one search helper; the PXWeb response flattener was factored into.px_flatten_response()and unit-tested; themongolstats.paralleloption is now registered and reported bynso_options().- The GeoBoundaries metadata request now uses the same timeout/retry policy as other requests.
- Selection mapping and validation consolidated into a single helper (
.px_map_selections()), removing three divergent copies of the logic. - Table resolution now goes through
.px_resolve_table()everywhere (.px_add_labels(),nso_table_periods(),.px_build_body()), removing the remaining inlined index lookups. - Integration tests resolve dimension codes from live metadata instead of assuming positional codes, so tests no longer break when NSO adds a new period. Integration and endpoint tests now assert concrete shapes and no longer swallow errors.
- Added
tools/record_fixtures.Rto record the httptest2 fixtures used bytest-recorded-*.R; those tests previously always skipped because the fixture directories were empty. - Removed unused
globalVariables()declarations, the unused lifecycle Suggests entry, and a stray rendered vignette HTML from the repository.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-05-27
- ERROR12 OK, 1 ERROR2026-05-22
- OK12 OK2026-04-25
Show 3 earlier changesHide 3 earlier changes
- NOTE11 OK, 3 NOTE2026-04-16
- ERROR10 OK, 3 NOTE, 1 ERROR2026-04-15
- NOTE11 OK, 3 NOTE2026-03-10
Documentation
The repository also keeps web-only articles.
- Help pages
- 32 (2 internal)includes a package overview page
- Examples that run
- 97%29 run in a plain check (21 of them under a condition) · 1 never run
- Exported functions with examples
- 100%
- Documented parameters
- 95%
- Return-value docs
- 100%
- Help pages citing references
- 0%
Downloads
Repository
- PRs merged (all time)
- 100%
- Median days to close, 50 most recently updated closed issues
- not measured
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Commits over time
14 development-tooling and community-health practices detected across 8 families in the upstream repository
Checks run against github.com/temuulene/mongolstats on 2026-10-18.
The R CMD check workflow runs on Linux, macOS and Windows
GitHub Pages site last deployed 2026-10-03 · The repository has a site deploy workflow
pkgdown site last built 2026-07-15
Show all practicesHide 4 practices
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2026-07-08Named in .Rbuildignore: .claudePull request it wrote: opened by a project member
Dependencies
Installing mongolstats adds 33 packages (24 with compiled code, 37 MB of source tarballs). Heaviest: stringi 11 MB, sf 9.3 MB, s2 2.8 MB.
Code & Tests
Datasets
People & History
Package metadata
- First published
- 2026-01-18
- Total releases
- 3 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 4.1.0
- Download size
- 1.3 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("mongolstats")The package provides a citation file that builds its entry when R runs it. Run citation() to see it.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-21, which the citation names so these numbers can be found later. More on citing and the projects behind them.