Nothing
#' Fetch European Central Bank (ECB) data
#'
#' Retrieve time series data from the ECB SDMX Web Service.
#'
#' @param flow (`character(1)`)\cr
#' Flow to query.
#' @param key (`NULL` | `character()`)\cr
#' The series keys to query.
#' @param start_period (`NULL` | `character(1)` | `integer(1)`)\cr
#' Start date of the data. Supported formats:
#' * YYYY for annual data (e.g., `2019`)
#' * YYYY-S\[1-2\] for semi-annual data (e.g., `"2019-S1"`)
#' * YYYY-Q\[1-4\] for quarterly data (e.g., `"2019-Q1"`)
#' * YYYY-MM for monthly data (e.g., `"2019-01"`)
#' * YYYY-W\[01-53\] for weekly data (e.g., `"2019-W01"`)
#' * YYYY-MM-DD for daily and business data (e.g., `"2019-01-01"`)
#'
#' If `NULL`, no start date restriction is applied (data retrieved from the earliest available
#' date). Default `NULL`.
#' @param end_period (`NULL` | `character(1)` | `integer(1)`)\cr
#' End date of the data, in the same format as start_period. If `NULL`, no end date restriction is
#' applied (data retrieved up to the most recent available date). Default `NULL`.
#' @param first_n (`NULL` | `numeric(1)`)\cr
#' Number of observations to retrieve from the start of the series. If `NULL`, no restriction is
#' applied. Default `NULL`.
#' @param last_n (`NULL` | `numeric(1)`)\cr
#' Number of observations to retrieve from the end of the series. If `NULL`, no restriction is
#' applied. Default `NULL`.
#' @param updated_after (`NULL` | `character(1)` | `Date(1)` | `POSIXct(1)`)\cr
#' Retrieve only observations updated after the given timestamp (e.g.,
#' `"2024-06-01T00:00:00"`). Useful for incremental retrieval. If `NULL`, no restriction is
#' applied. Default `NULL`.
#' @returns A [data.table::data.table()] with the requested data.
#' @source <https://data.ecb.europa.eu/help/api/data>
#' @family data
#' @export
#' @examplesIf curl::has_internet()
#' \donttest{
#' # fetch US dollar/Euro exchange rate
#' ecb_data("EXR", "D.USD.EUR.SP00.A")
#'
#' # fetch data for multiple keys
#' ecb_data("EXR", c("D.USD", "JPY.EUR.SP00.A"))
#' }
ecb_data = function(
flow,
key = NULL,
start_period = NULL,
end_period = NULL,
first_n = NULL,
last_n = NULL,
updated_after = NULL
) {
assert_string(flow, min.chars = 1L)
assert_character(key, min.chars = 1L, min.len = 1L, any.missing = FALSE, null.ok = TRUE)
assert_period(start_period)
assert_period(end_period)
first_n = assert_count(first_n, null.ok = TRUE, positive = TRUE, coerce = TRUE)
last_n = assert_count(last_n, null.ok = TRUE, positive = TRUE, coerce = TRUE)
updated_after = assert_timestampish(updated_after, null.ok = TRUE)
resource = sdmx_data_resource(flow, key, default_key = "all")
xml = ecb(
resource = resource,
accept = "application/vnd.sdmx.genericdata+xml;version=2.1",
startPeriod = start_period,
endPeriod = end_period,
firstNObservations = first_n,
lastNObservations = last_n,
updatedAfter = updated_after
)
parse_ecb_data(xml)
}
#' Fetch European Central Bank (ECB) metadata
#'
#' Retrieve metadata from the ECB time series database via the SDMX Web Service.
#'
#' @param type (`character(1)`)\cr
#' The type of metadata to query. One of: `"datastructure"`, `"dataflow"`, `"codelist"`, or
#' `"concept"`.
#' @param agency (`NULL` | `character(1)`)\cr
#' The id of the agency to query. Default `NULL`.
#' @param id (`NULL` | `character(1)`)\cr
#' The id of the resource to query. Default `NULL`.
#' @returns A [data.table::data.table()] with the requested metadata.
#' The columns are:
#' \item{agency}{The agency of the metadata}
#' \item{id}{The id of the metadata}
#' \item{name}{The name of the metadata}
#' @source <https://data.ecb.europa.eu/help/api/metadata>
#' @family metadata
#' @export
#' @examplesIf curl::has_internet()
#' \donttest{
#' ecb_metadata("datastructure")
#' ecb_metadata("datastructure", "ECB")
#' ecb_metadata("datastructure", "ECB", "ECB_EXR1")
#' ecb_metadata("datastructure", id = "ECB_EXR1")
#' }
ecb_metadata = function(type, agency = NULL, id = NULL) {
assert_choice(type, c("datastructure", "dataflow", "codelist", "concept"))
meta = sdmx_metadata_type(type)
fetch_ecb_metadata(meta$resource, meta$xpath, agency, id)
}
#' Fetch European Central Bank (ECB) dimensions
#'
#' Retrieve the dimension structure for a given dataflow from the ECB SDMX Web Service.
#'
#' @param id (`character(1)`)\cr
#' The id of the data structure definition to query (e.g., `"ECB_EXR1"`).
#' @returns A [data.table::data.table()] with columns:
#' \item{id}{The dimension id (e.g., `"FREQ"`, `"CURRENCY"`)}
#' \item{position}{The position of the dimension in the series key}
#' \item{codelist}{The id of the associated codelist (e.g., `"CL_FREQ"`)}
#' @source <https://data.ecb.europa.eu/help/api/metadata>
#' @family metadata
#' @export
#' @examplesIf curl::has_internet()
#' \donttest{
#' ecb_dimension("ECB_EXR1")
#' }
ecb_dimension = function(id) {
assert_string(id, min.chars = 1L)
resource = paste("datastructure", "ECB", toupper(id), sep = "/")
xml = ecb(resource)
sdmx_dimension(xml)
}
fetch_ecb_metadata = function(resource, xpath, agency = NULL, id = NULL) {
assert_string(agency, min.chars = 1L, null.ok = TRUE)
assert_string(id, min.chars = 1L, null.ok = TRUE)
agency = if (!is.null(agency)) toupper(agency) else "all"
id = if (!is.null(id)) toupper(id) else "all"
resource = paste(resource, agency, id, sep = "/")
xml = ecb(resource)
entries = xml2::xml_find_all(xml, xpath)
parse_ecb_metadata(entries)
}
parse_ecb_data = function(xml) {
series = xml2::xml_find_all(xml, ".//generic:Series")
res = map(series, function(x) {
series_key = x |>
xml2::xml_find_first(".//generic:SeriesKey") |>
xml2::xml_children()
nms = series_key |>
xml2::xml_attr("id") |>
tolower()
series_key = series_key |>
xml2::xml_attr("value") |>
setNames(nms) |>
as.list()
attrs = x |>
xml2::xml_find_first("./generic:Attributes") |>
xml2::xml_children()
nms = attrs |>
xml2::xml_attr("id") |>
tolower()
nms = replace(nms, nms == "title_compl", "description")
attrs = attrs |>
xml2::xml_attr("value") |>
setNames(nms) |>
as.list()
data = c(series_key, attrs)
data$key = paste(series_key, collapse = ".")
data$freq = sdmx_freq(data$freq)
entries = xml2::xml_find_all(x, ".//generic:Obs[generic:ObsValue]")
data$date = entries |>
xml2::xml_find_all(".//generic:ObsDimension") |>
xml2::xml_attr("value") |>
parse_date(data$freq)
data$value = entries |>
xml2::xml_find_all(".//generic:ObsValue") |>
xml2::xml_attr("value") |>
as.numeric()
as.data.table(data)
})
res = res |>
rbindlist(fill = TRUE) |>
setcolorder(col_order, skip_absent = TRUE)
res[]
}
parse_ecb_metadata = function(entries) {
agency = NULL
dt = entries |>
map(function(node) {
dt = sdmx_metadata(list(node))
dt[, agency := xml2::xml_attr(node, "agencyID")]
}) |>
rbindlist() |>
setcolorder(c("agency", "id", "name"))
dt[]
}
ecb_error_body = function(resp) {
sdmx_error_body(resp, docs = "See docs at <https://data.ecb.europa.eu/help/api/status-codes>")
}
ecb = function(resource, ..., accept = NULL) {
sdmx_request(
"https://data-api.ecb.europa.eu/service/",
resource,
ecb_error_body,
...,
accept = accept
)
}
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.