knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(OECDdata) library(data.table) library(magrittr) old <- oecdOptions(quiet = TRUE, open_browser = FALSE, return_data_table = TRUE, strings_as_factors = FALSE)
Discover a dataflow, inspect its dimensions and dictionaries, restrict the
request, inspect status and units, and only then calculate statistics. The
eurodata package inspires the workflow, but names, classes and identities
are OECD-native.
The default route is SDMX REST v2. See the package README for current protocol
references and a detailed interface and migration guide.
All evaluated chunks in this vignette are offline. The following object contains invented teaching observations, not actual OECD statistics.
x <- oecdExample() x[, .(REF_AREA, TIME_PERIOD, value_, flags_)]
attr(x, "Dimensions") attr(x, "OECDAttributes") str(x)
value_ is numeric. Dimension codes remain strings or, with the default options,
factors. Numeric-looking identifiers retain leading zeros. flags_ preserves
OBS_STATUS without translating it into another provider's status vocabulary.
The original attribute is retained too.
series_keys <- setdiff(attr(x, "Dimensions"), "TIME_PERIOD") x[, .(observations = .N, missing = sum(is.na(value_))), by = series_keys] x[, .N, by = OBS_STATUS]
An incomplete series is not automatically filled with zeros. An attribute such
as UNIT_MULT is not automatically applied: verify whether the reported value
and the unit metadata require scaling in your analysis.
This synthetic example contains one frequency, measure and group per country. Check that simplification before dropping those columns.
stopifnot(x[, uniqueN(FREQ)] == 1L, x[, uniqueN(MEASURE)] == 1L, x[, uniqueN(GROUP)] == 1L, !anyDuplicated(x, by = c("TIME_PERIOD", "REF_AREA"))) dcast(x, TIME_PERIOD ~ REF_AREA, value.var = "value_")
one <- x[REF_AREA == "USA"][order(TIME_PERIOD)] plot(as.Date(paste0(one$TIME_PERIOD, "-01")), one$value_, type = "l", xlab = "Month", ylab = "Synthetic index", main = "Invented example")
Sorting is necessary but not sufficient. Check that observations are exactly one month apart, so a gap is not misinterpreted as one month's growth.
copy(x) %>% .[, month_id := as.integer(substr(TIME_PERIOD, 1, 4)) * 12L + as.integer(substr(TIME_PERIOD, 6, 7))] %>% .[order(month_id), `:=`(previous = shift(value_), previous_month = shift(month_id)), by = series_keys] %>% .[, growth_pct := fifelse(!is.na(previous) & previous != 0 & month_id - previous_month == 1L, 100 * (value_ / previous - 1), NA_real_)] %>% .[, .(REF_AREA, TIME_PERIOD, growth_pct)]
OECDdata::find("health expenditure") OECDdata::find(education, expenditure) browseDataList(grepl("employment", `Dataset name`, ignore.case = TRUE)) code <- "CLI" s <- oecdStructure(code) s$flow s$dimensions s$labels$REF_AREA importLabels("REF_AREA", dataset = code) describe(code, wide = TRUE)
A codelist describes permissible values. An Actual content constraint can
establish reported marginal availability, but not that every combination of
values is observed. describe() and importMetabase() fail explicitly when
that coverage cannot be established. availability = "allowed" is an explicit
alternative for dictionary-based inventories, not a substitute presented as
observed coverage.
A short code is matched against the current catalogue, not a hard-coded alias list. Ambiguity is an error. Agency and dataflow-prefix selectors can resolve it without making the dataset code harder to read. Resolve once for reuse:
ref <- oecdDataset("CLI", agency = "OECD.SDD.STES", prefix = "DSD_STES") ref importLabels(OECDDimCode = "REF_AREA", dataset = ref) # A query preview fetches metadata but does not download observations. oecdQuery("CLI", filters = list( .dataset = list(agency = "OECD.SDD.STES", prefix = "DSD_STES"), REF_AREA = "USA", FREQ = "M", TIME_PERIOD = c("2023-01", "2023-12") ))
The reserved .dataset block selects agency, dataflow namespace and/or version;
it is not a set of series dimensions. prefix matches the dataflow ID prefix
before @. The actual referenced DSD is read from the server metadata. All other
filter entries retain their ordinary dimension semantics. A selector-only block
leaves all observations unrestricted. A qualified reference avoids the catalogue
lookup, and explicit selector/reference conflicts are errors.
cli <- importData(code, list(REF_AREA = c("USA", "FRA"), FREQ = "M", TIME_PERIOD = c("2023-01", "2023-12"))) attr(cli, "SourceURL") attr(cli, "OECDDatasetCode")
The two time bounds define an inclusive range. An unspecified dimension is a wildcard, so the result may include multiple measures or transformations. Never collapse them into a single line or aggregate solely by country and date without checking the other key dimensions.
Requests are cached in a session temporary directory by default. Persistent storage is opt-in. Offline mode accepts expired but verified cache entries; missing or corrupt entries cause explicit errors. Cached data retain their original download time. A structure version is not a statistical vintage.
attributes(x)[c("RequestedDatasetCode", "OECDDatasetCode", "DownloadTime", "SourceURL", "Dimensions")]
oecdOptions(cache_dir = tools::R_user_dir("OECDdata", "cache")) # First make a successful online request with the desired metadata and filters. # Then use offline = TRUE with the same request. saveRDS(list(data = cli, provenance = attributes(cli)), "cli-snapshot.rds")
HTTP failures remain structured errors. HTTP 204 is an explicit empty result with a warning. The client never converts an arbitrary 404 or malformed response into an apparently successful empty dataset.
options(old)
Use old <- oecdOptions(...) with on.exit(options(old)) inside your own
functions to keep option changes local. The package itself does not change
options at load time.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.