Provides deterministic tools for auditing whether artificial intelligence systems preserve the numerical, semantic, contextual, temporal, geographic, unit, provenance, revision, transformation, and uncertainty properties of official statistics. Structured reference statistics and machine-generated claims can be compared using non-compensatory critical-error rules, weakest-link and geometric fidelity summaries, provenance graphs, and portable SHA-256 proof bundles. The package provides bounded connectors for official statistical services, an easy schema-detection and file-import layer for arbitrary official organisations, extensible provider registries, and a search-first natural- language verification layer that classifies statistical claims, selects suitable official sources, retrieves candidate evidence, matches statistical dimensions, and compares claimed values. If no reference year is stated, verification uses the latest available matching official observation and discloses the resolved year. Source attribution is optional: automatic routing can choose suitable providers when none is named, while explicitly named supported sources are respected by default. Automatic catalogue-to-observation verification is implemented for the World Bank, WHO, the United Nations Statistics Division Sustainable Development Goals service, and the European Commission statistical service, while other providers remain available through bounded direct connectors or generic official-data import. Prompt perturbation, statistical red-team generation, minimal-pair tests, and benchmark data support reproducible evaluation of generative, retrieval-augmented, and agentic statistical systems. An embedded alignment layer maps claim-level controls to relevant activities of the Generic Statistical Business Process Model (GSBPM) 5.2, including Analyse, Disseminate, Evaluate, Quality Management, and Metadata Management.
AI4OfficialStats audits whether AI-mediated answers preserve the statistical meaning of official data. It is designed for generative AI, retrieval-augmented generation (RAG), statistical agents, and model-context-protocol style tool workflows without depending on a particular model vendor.
Authors, in package citation order:
Maintainer: Leila Marvian Mashhad.
AI4OfficialStats is designed to complement, not replace, the Generic Statistical Business Process Model (GSBPM) 5.2. GSBPM is a process-level reference model for the production of official statistics, covering activities from specifying needs and design through collection, processing, analysis, dissemination, and evaluation. AI4OfficialStats addresses a narrower executable problem at the statistical-claim level: whether the multidimensional meaning of an official statistical object is preserved when it is retrieved, transformed, summarised, or communicated through generative AI, retrieval-augmented generation (RAG), or statistical agents.
The closest operational alignment is with GSBPM activities related to Analyse, Disseminate, Evaluate, and overarching Quality Management. The package does not implement the GSBPM production process. Instead, it provides claim-level controls that can sit within or alongside those activities:
PASS / WARN / FAIL decisions;A useful distinction is: GSBPM provides the process-level quality architecture; AI4OfficialStats provides an executable AI claim-level fidelity-control layer.
Official GSBPM 5.2 information: https://unece.org/statistics/gsbpm-v5.2
This relationship is implemented directly in the package:
# Embedded offline mapping of relevant GSBPM 5.2 activities
gsbpm52_map()
# Where a fidelity dimension or package function fits
gsbpm_align("geographic")
gsbpm_align("audit_stat_ai")
# After an audit, create a GSBPM-oriented quality evidence report
# report <- gsbpm_quality_report(aud)
# report
The mapping deliberately uses the terms direct and supporting, not
"compliant" or "certified". GSBPM 5.2 is a reference model for statistical
business processes; AI4OfficialStats supplies executable evidence that can support
selected GSBPM activities.
audit_stats(), read_official_stats(), automatic schema detection, and plain-text claim conversion;readxl package is installed;search_official_stats(), including WHO and the Eurostat Catalogue API;stat_provider_data representation and more flexible as_stat_reference() conversion;For most users, version 0.2.0 no longer requires manually constructing every canonical object before an audit. Ordinary tabular data can be used directly:
library(AI4OfficialStats)
d <- data.frame(
Value = 10.4,
Indicator = "unemployment rate",
Country = "Spain",
Year = 2025,
Unit = "percent",
Source = "Example NSO"
)
audit_stats(d, "The reported value is 10.4%.")
The same importer recognizes common Persian field names:
iran <- data.frame(
"مقدار" = "۱۲٫۵",
"عنوان شاخص" = "نرخ بیکاری",
"کشور" = "ایران",
"سال" = "۱۴۰۳",
"واحد" = "درصد",
check.names = FALSE
)
x <- read_official_stats(iran, provider = "Statistical Center of Iran")
ref <- as_stat_reference(x)
When automatic detection is insufficient, only the ambiguous fields need to be mapped explicitly:
x <- read_official_stats(
d,
provider = "Example NSO",
mapping = list(value = "Value", geo = "Country", time = "Year")
)
A provider does not need a dedicated connector. Register a session-local profile with its preferred schema and host patterns:
register_official_provider(
"my_nso",
provider_label = "My National Statistical Office",
mapping = list(value = "OBS_VALUE", geo = "AREA", time = "YEAR"),
host_patterns = "data.example.gov",
overwrite = TRUE
)
x <- read_official_stats("official_file.csv", provider = "my_nso")
This generic layer is the intended path for statistical offices, ministries, central banks, and other official organisations whose files or APIs do not yet have a package-specific connector.
library(AI4OfficialStats)
ref <- stat_reference(
value = 10.4,
indicator = "unemployment rate",
geo = "Spain",
time = "2025",
unit = "percent",
source = "Eurostat",
dataset = "example_lfs",
population = "labour force"
)
claim <- stat_claim(
value = 10.4,
indicator = "unemployment rate",
geo = "Spain",
time = "2025",
unit = "%",
source = "Eurostat",
dataset = "example_lfs",
population = "labour force"
)
aud <- audit_stat_ai(ref, claim)
aud
proof <- certify_claim(aud)
verify_proof(proof)
The provider registry distinguishes three levels of support instead of treating every organisation as equivalent:
Use official_stat_providers() to inspect these capabilities programmatically. The generic layer means an organisation does not need to be hard-coded before its official CSV/Excel/JSON/URL evidence can be audited.
The package builds requests against documented official provider endpoints. Network access happens only when a search/fetch/verification function is explicitly called. Session-local caching is enabled by default; it can be disabled with cache = FALSE or redirected with cache_dir.
# Eurostat catalogue URL and Statistics API URL (offline)
eurostat_catalogue_url()
eurostat_url("demo_pjan", list(geo = "ES", time = "2025", sex = "T"))
# World Bank URL only (offline)
worldbank_url("SP.POP.TOTL", country = "FRA", start = 2020, end = 2025)
# OECD URL only (offline)
oecd_url("OECD.SDD.STES", "DSD_STES@DF_CLI", start_period = "2025")
Live retrieval examples:
# Requires internet access
# wb <- fetch_worldbank("SP.POP.TOTL", country = "FRA", start = 2025, end = 2025)
# ref <- as_stat_reference(wb, row = 1, unit = "persons")
# Requires internet access
# hits <- search_official_stats(
# "unemployment",
# providers = c("worldbank", "unsd_sdg", "who", "eurostat")
# )
# hits
# Session-local registration; no secret is written to disk.
register_stat_api(
"my_nso",
base_url = "https://api.example.gov/v1",
search_path = "search",
query_param = "q",
api_key_name = "api_key",
provider_label = "Example National Statistical Office"
)
# Optional key for the current R process only:
# set_stat_api_key("my_nso", "YOUR_KEY")
# search_stat_api("my_nso", "population")
Additional built-in endpoints:
# UNSD SDG metadata search and series data
# search_unsd_sdg("social protection")
# sdg <- fetch_unsd_sdg("SI_COV_SOCINS", page_size = 100)
# UK ONS full-text search
# search_ons("unemployment", content_type = "dataset")
# BLS public single-series retrieval
# bls <- fetch_bls("LNS14000000", latest = TRUE)
# IMF SDMX URL builder
imf_api_url("dataflow/IMF/all/latest", version = "3.0")
Provider documentation used by this package:
WHO indicator metadata and observations can be searched or fetched with the OData connector:
# URL construction is offline
who_odata_url(
"WHOSIS_000001",
filter = "SpatialDim eq 'IRN'",
top = 100
)
# Requires internet access
# search_who("life expectancy")
# who <- fetch_who("WHOSIS_000001", country = "IRN", year = 2024,
# unit = "years", indicator_name = "Life expectancy at birth")
WHO is migrating from the older GHO OData implementation to the World Health Data Hub OData implementation. For forward compatibility the base URL is not hard-wired into user code:
options(AI4OfficialStats.who_base_url = "https://new-who-odata.example/")
The packaged default uses the last publicly documented GHO OData endpoint and
can be overridden with the option above or the base_url argument.
ref <- stat_reference(
-0.7, "unemployment-rate change", "Exampleland", "2024-2025",
"percentage points", "Official provider",
transformation = list(
operation = "percentage point change",
inputs = c(11.1, 10.4), result = -0.7
)
)
claim <- stat_claim(
-6.31, "unemployment-rate change", "Exampleland", "2024-2025",
"percent", "Official provider",
transformation = list(
operation = "percent change",
inputs = c(11.1, 10.4), result = -6.31
)
)
audit_stat_ai(ref, claim)
head(officialstat_benchmark())
benchmark_from_reference(ref)
Live API calls are not required by tests or runnable examples. Parser tests use local fixtures. Provider requests are bounded, cached in the session by default, and only occur after an explicit user call. Before CRAN submission, build the source tarball with the current R release or R-patched and run R CMD check --as-cran on that built tarball.
Version 0.2.0 adds a search-first interface for users who do not already have a reference row. A statement can be parsed, categorised, routed to appropriate official providers, searched, retrieved, dimension-matched, and then compared.
p <- classify_stat_claim(
"Iran's unemployment rate was 8.1 percent in 2025."
)
p
suggest_stat_providers(p)
For live official-source verification:
result <- verify_claim(
"Iran's unemployment rate was 8.1 percent in 2025."
)
result
The source name is optional. With the default providers = "auto", the package
selects suitable automatic-verification providers from the detected statistical
domain and reports the provider actually used. If the claim explicitly names a
supported source, that attribution is respected by default.
The reference year is optional too. If a claim contains no year and no explicit
latest-time phrase, verify_claim() uses the latest available matching official
observation. The printed result explicitly reports that the time was selected
automatically and shows the official reference year that was used.
# No source and no year: both are resolved by the package.
result <- verify_claim(
"Iran's population was 91 million."
)
result
# Automatic source selection
result <- verify_claim(
"Life expectancy in Iran was 77 years in 2023.",
providers = "auto"
)
# Compare the same unattributed claim separately across every provider
# with full automatic-verification support.
# result_all <- verify_claim(
# "Life expectancy in Iran was 77 years in 2023.",
# providers = "all"
# )
When a source is explicitly named, automatic verification stays with that source when a full connector is available:
# Requires internet access
# result <- verify_claim(
# "According to Eurostat, Spain's unemployment rate was 10.5 percent in 2025."
# )
# result
The verifier does not confirm a claim merely because it finds the same number. It matches the indicator, geography, time/latest-time intent, unit, and aggregate/disaggregation context before comparing the value. The selected source URL and official observation are retained in the result.
You can also use the same workflow fully offline with an official file or data frame:
official <- data.frame(
value = 7.8,
indicator = "unemployment rate",
country = "Iran",
year = 2025,
unit = "percent",
source = "Example official source"
)
verify_claim(
"Iran's unemployment rate was 8.1 percent in 2025.",
evidence = official
)
Persian text and digits are supported for common statistical concepts:
classify_stat_claim(
"نرخ بیکاری ایران در سال ۲۰۲۵ برابر با ۸٫۱ درصد بود."
)
For paragraphs with multiple numerical statistical statements, use
verify_text(). Full per-claim verification objects are stored in the returned
batch object's verifications attribute.
Automatic live retrieval is intentionally limited to providers for which the
package has both searchable metadata and bounded data-retrieval logic. Other
national and international organisations can still be used through
read_official_stats(), register_official_provider(), custom APIs, or the
evidence= argument to verify_claim().