The cnbrrr
package provides a convenient interface to
the Czech National Bank’s ARAD (Aggregated data of the CNB) API for
accessing economic and financial data.
Installation
Install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("petrbouchal/cnbrrr")
Setup
Before using the package, obtain an API key from the Czech National Bank and set it as an environment variable:
# Set your API key
Sys.setenv(ARAD_API_KEY = "your_api_key_here")
Alternatively, you can pass the API key directly to function calls.
Core workflow
1. Discover available data
Start by exploring what indicators are available. The ARAD API provides several endpoints for discovering indicators:
library(cnbrrr)
# Get indicators from a specific data set (replace with actual set_id)
indicators <- arad_list_indicators(set_id = 1115, filter = "podnik")
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
head(indicators)
#> Error in eval(expr, envir, enclos): object 'indicators' not found
# Filter indicators by name within a data set
gdp_indicators <- arad_list_indicators(set_id = 1032, filter = "Místní vládní instituce")
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
gdp_indicators
#> Error in eval(expr, envir, enclos): object 'gdp_indicators' not found
# Get specific indicators by indicator IDs
specific_indicators <- arad_list_indicators(indicator_id_list = "SFU2QS1313L05T")
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
specific_indicators
#> Error in eval(expr, envir, enclos): object 'specific_indicators' not found
# Get multiple indicators by their IDs
multiple_indicators <- arad_list_indicators(indicator_id_list = c("SFU2QS1313L05T", "SFU2QS1313A06LE"))
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
multiple_indicators
#> Error in eval(expr, envir, enclos): object 'multiple_indicators' not found
# Get indicators from a named selection in your ARAD account
selection_indicators <- arad_list_indicators(selection_id = "my_selection")
selection_indicators
Explore the structure and organization of indicators:
# Get indicator dimensions (shows how indicators are organized)
indicators_in_base <- arad_list_indicators(base_id = "MBOP")
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
head(indicators_in_base)
#> Error in eval(expr, envir, enclos): object 'indicators_in_base' not found
# Get dimensional structure for a specific set
dims <- arad_indicators_dims(set_id = 1115)
#> Error in value[[3L]](cond): Failed to retrieve indicator dimensions from ARAD API: HTTP 400 Bad Request.
head(dims)
#> Error in eval(expr, envir, enclos): object 'dims' not found
# Get dimensions for specific indicators
specific_dims <- arad_indicators_dims(indicator_id_list = c("SFU2QS1313L05T", "SFU2QS1313A06LE"))
#> Error in value[[3L]](cond): Failed to retrieve indicator dimensions from ARAD API: HTTP 400 Bad Request.
specific_dims
#> Error in eval(expr, envir, enclos): object 'specific_dims' not found
# Get dimensions from a named selection
selection_dims <- arad_indicators_dims(selection_id = "my_selection")
selection_dims
# Get the hierarchical tree structure of indicators
tree <- arad_indicators_tree(set_id = 1115)
#> Error in value[[3L]](cond): Failed to retrieve indicator tree from ARAD API: HTTP 400 Bad Request.
head(tree)
#> Error in eval(expr, envir, enclos): object 'tree' not found
# Get tree structure for specific indicators
specific_tree <- arad_indicators_tree(indicator_id_list = c("SFU2QS1313L05T", "SFU2QS1313A06LE"))
#> Error in value[[3L]](cond): Failed to retrieve indicator tree from ARAD API: HTTP 400 Bad Request.
specific_tree
#> Error in eval(expr, envir, enclos): object 'specific_tree' not found
# Get tree structure from a named selection
selection_tree <- arad_indicators_tree(selection_id = "my_selection")
selection_tree
Finding IDs: To effectively use these functions, browse the ARAD web interface to find: - set_id: Identifies data sets (collections of related indicators) - base_id: Identifies specific indicators within sets - indicators_list: Use specific indicator IDs when you know exactly which indicators you need (e.g., “SRUMD08402”) - selection_id: Use named selections you’ve created in your ARAD user account to group indicators
2. Retrieve data for specific indicators
Get time series data for the indicators you need:
# Get data for a single indicator
data <- arad_get_data(c("MBOPCAHDPPECY", "MBOPCCHDPPECY"))
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
data
#> function (..., list = character(), package = NULL, lib.loc = NULL,
#> verbose = getOption("verbose"), envir = .GlobalEnv, overwrite = TRUE)
#> {
#> fileExt <- function(x) {
#> db <- grepl("\\.[^.]+\\.(gz|bz2|xz)$", x)
#> ans <- sub(".*\\.", "", x)
#> ans[db] <- sub(".*\\.([^.]+\\.)(gz|bz2|xz)$", "\\1\\2",
#> x[db])
#> ans
#> }
#> my_read_table <- function(...) {
#> lcc <- Sys.getlocale("LC_COLLATE")
#> on.exit(Sys.setlocale("LC_COLLATE", lcc))
#> Sys.setlocale("LC_COLLATE", "C")
#> read.table(...)
#> }
#> stopifnot(is.character(list))
#> names <- c(as.character(substitute(list(...))[-1L]), list)
#> if (!is.null(package)) {
#> if (!is.character(package))
#> stop("'package' must be a character vector or NULL")
#> }
#> paths <- find.package(package, lib.loc, verbose = verbose)
#> if (is.null(lib.loc))
#> paths <- c(path.package(package, TRUE), if (!length(package)) getwd(),
#> paths)
#> paths <- unique(normalizePath(paths[file.exists(paths)]))
#> paths <- paths[dir.exists(file.path(paths, "data"))]
#> dataExts <- tools:::.make_file_exts("data")
#> if (length(names) == 0L) {
#> db <- matrix(character(), nrow = 0L, ncol = 4L)
#> for (path in paths) {
#> entries <- NULL
#> packageName <- if (file_test("-f", file.path(path,
#> "DESCRIPTION")))
#> basename(path)
#> else "."
#> if (file_test("-f", INDEX <- file.path(path, "Meta",
#> "data.rds"))) {
#> entries <- readRDS(INDEX)
#> }
#> else {
#> dataDir <- file.path(path, "data")
#> entries <- tools::list_files_with_type(dataDir,
#> "data")
#> if (length(entries)) {
#> entries <- unique(tools::file_path_sans_ext(basename(entries)))
#> entries <- cbind(entries, "")
#> }
#> }
#> if (NROW(entries)) {
#> if (is.matrix(entries) && ncol(entries) == 2L)
#> db <- rbind(db, cbind(packageName, dirname(path),
#> entries))
#> else warning(gettextf("data index for package %s is invalid and will be ignored",
#> sQuote(packageName)), domain = NA, call. = FALSE)
#> }
#> }
#> colnames(db) <- c("Package", "LibPath", "Item", "Title")
#> footer <- if (missing(package))
#> paste0("Use ", sQuote(paste("data(package =", ".packages(all.available = TRUE))")),
#> "\n", "to list the data sets in all *available* packages.")
#> else NULL
#> y <- list(title = "Data sets", header = NULL, results = db,
#> footer = footer)
#> class(y) <- "packageIQR"
#> return(y)
#> }
#> paths <- file.path(paths, "data")
#> for (name in names) {
#> found <- FALSE
#> for (p in paths) {
#> tmp_env <- if (overwrite)
#> envir
#> else new.env()
#> if (file_test("-f", file.path(p, "Rdata.rds"))) {
#> rds <- readRDS(file.path(p, "Rdata.rds"))
#> if (name %in% names(rds)) {
#> found <- TRUE
#> if (verbose)
#> message(sprintf("name=%s:\t found in Rdata.rds",
#> name), domain = NA)
#> thispkg <- sub(".*/([^/]*)/data$", "\\1", p)
#> thispkg <- sub("_.*$", "", thispkg)
#> thispkg <- paste0("package:", thispkg)
#> objs <- rds[[name]]
#> lazyLoad(file.path(p, "Rdata"), envir = tmp_env,
#> filter = function(x) x %in% objs)
#> break
#> }
#> else if (verbose)
#> message(sprintf("name=%s:\t NOT found in names() of Rdata.rds, i.e.,\n\t%s\n",
#> name, paste(names(rds), collapse = ",")),
#> domain = NA)
#> }
#> files <- list.files(p, full.names = TRUE)
#> files <- files[grep(name, files, fixed = TRUE)]
#> if (length(files) > 1L) {
#> o <- match(fileExt(files), dataExts, nomatch = 100L)
#> paths0 <- dirname(files)
#> paths0 <- factor(paths0, levels = unique(paths0))
#> files <- files[order(paths0, o)]
#> }
#> if (length(files)) {
#> for (file in files) {
#> if (verbose)
#> message("name=", name, ":\t file= ...", .Platform$file.sep,
#> basename(file), "::\t", appendLF = FALSE,
#> domain = NA)
#> ext <- fileExt(file)
#> if (basename(file) != paste0(name, ".", ext))
#> found <- FALSE
#> else {
#> found <- TRUE
#> switch(ext, R = , r = {
#> library("utils")
#> sys.source(file, chdir = TRUE, envir = tmp_env)
#> }, RData = , rdata = , rda = load(file, envir = tmp_env),
#> TXT = , txt = , tab = , tab.gz = , tab.bz2 = ,
#> tab.xz = , txt.gz = , txt.bz2 = , txt.xz = assign(name,
#> my_read_table(file, header = TRUE, as.is = FALSE),
#> envir = tmp_env), CSV = , csv = , csv.gz = ,
#> csv.bz2 = , csv.xz = assign(name, my_read_table(file,
#> header = TRUE, sep = ";", as.is = FALSE),
#> envir = tmp_env), found <- FALSE)
#> }
#> if (found)
#> break
#> }
#> if (verbose)
#> message(if (!found)
#> "*NOT* ", "found", domain = NA)
#> }
#> if (found)
#> break
#> }
#> if (!found) {
#> warning(gettextf("data set %s not found", sQuote(name)),
#> domain = NA)
#> }
#> else if (!overwrite) {
#> for (o in ls(envir = tmp_env, all.names = TRUE)) {
#> if (exists(o, envir = envir, inherits = FALSE))
#> warning(gettextf("an object named %s already exists and will not be overwritten",
#> sQuote(o)))
#> else assign(o, get(o, envir = tmp_env, inherits = FALSE),
#> envir = envir)
#> }
#> rm(tmp_env)
#> }
#> }
#> invisible(names)
#> }
#> <bytecode: 0x10f68ee78>
#> <environment: namespace:utils>
# Get data for multiple indicators at once
multi_data <- arad_get_data(indicator_ids = c("MBOPCAHDPPECY", "MBOPCCHDPPECY"),
period_to = "20231231",
period_from = "20201031")
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
multi_data
#> Error in eval(expr, envir, enclos): object 'multi_data' not found
# Get raw data without processing (returns raw CSV data)
raw_data <- arad_get_data("SRUMD08402C", process_data = FALSE)
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
# Get data with both filters and rename the value column
spending <- arad_get_data("SRUMD08402C",
period_from = "20121231",
period_to = "20241231",
rename_value = "government_spending")
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
spending
#> Error in eval(expr, envir, enclos): object 'spending' not found
Working with indicator structure
You can explore how indicators are organized using the dimension and tree functions covered in the discovery section above. These provide insights into the hierarchical structure and dimensional organization of the ARAD data.
Utility functions
The package includes several helper functions:
# Validate indicator ID format
valid_ids <- arad_validate_indicators(c("SRUMD08402C", "INVALID_ID"))
valid_ids
#> [1] TRUE FALSE
# Parse ARAD date format manually
dates <- arad_parse_date(c("20231201", "20231101"))
dates
#> [1] "2023-12-01 UTC" "2023-11-01 UTC"
Complete analysis example
Here’s a full workflow for analyzing Czech economic data:
library(cnbrrr)
library(dplyr)
library(ggplot2)
# 1. Find relevant indicators
indicators <- arad_list_indicators(base_id = "SHDPZDR", filter = "HDP")
#> Error in value[[3L]](cond): Failed to retrieve indicators from ARAD API: HTTP 400 Bad Request.
print(head(indicators))
#> Error in eval(expr, envir, enclos): object 'indicators' not found
# 2. Get the data (assuming we found a GDP indicator)
gdp_data <- arad_get_data("SRUMD08402C",
rename_value = "gdp") |>
filter(lubridate::month(period) == 12)
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
# 3. Process and analyze
recent_gdp <- gdp_data |>
filter(year >= 2010) |>
arrange(year) |>
mutate(
gdp_growth = (gdp / lag(gdp) - 1) * 100,
is_recession = gdp_growth < 0
)
#> Error in eval(expr, envir, enclos): object 'gdp_data' not found
# 4. Summary statistics
gdp_summary <- recent_gdp |>
summarise(
mean_gdp = mean(gdp, na.rm = TRUE),
mean_growth = mean(gdp_growth, na.rm = TRUE),
latest_year = max(year, na.rm = TRUE),
latest_gdp = gdp[year == latest_year][1],
recession_years = sum(is_recession, na.rm = TRUE)
)
#> Error in eval(expr, envir, enclos): object 'recent_gdp' not found
print(gdp_summary)
#> Error in eval(expr, envir, enclos): object 'gdp_summary' not found
# 5. Create visualization
gdp_plot <- ggplot(recent_gdp, aes(x = year, y = gdp)) +
geom_line(color = "#0000ff", size = 1.2) +
geom_point(color = "#0000ff", size = 2) +
geom_point(data = filter(recent_gdp, is_recession),
color = "red", size = 3, alpha = 0.7) +
labs(
title = "Czech GDP Trend",
subtitle = "Annual data from Czech National Bank ARAD. Red points indicate recession years.",
x = "Year",
y = "GDP Value",
caption = "Source: Czech National Bank ARAD API via cnbrrr package"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold", color = "#001F3F"),
plot.subtitle = element_text(size = 12, color = "gray60"),
text = element_text(color = "#001F3F")
)
#> Error in eval(expr, envir, enclos): object 'recent_gdp' not found
print(gdp_plot)
#> Error in eval(expr, envir, enclos): object 'gdp_plot' not found
# 6. Growth rate visualization
growth_plot <- ggplot(recent_gdp, aes(x = year, y = gdp_growth)) +
geom_col(aes(fill = is_recession), alpha = 0.8) +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
scale_fill_manual(values = c("FALSE" = "#0000ff", "TRUE" = "red")) +
labs(
title = "Czech GDP Growth Rate",
subtitle = "Year-over-year percentage change",
x = "Year",
y = "GDP Growth (%)",
fill = "Recession",
caption = "Source: Czech National Bank ARAD API via cnbrrr package"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold", color = "#001F3F"),
plot.subtitle = element_text(size = 12, color = "gray60"),
text = element_text(color = "#001F3F"),
legend.position = "bottom"
)
#> Error in eval(expr, envir, enclos): object 'recent_gdp' not found
print(growth_plot)
#> Error in eval(expr, envir, enclos): object 'growth_plot' not found
Data format and structure
All functions return data frames with consistent column structure:
-
period
: Date object (converted from YYYYMMDD format) -
value
: Numeric data values -
year
: Extracted year from period -
month
: Extracted month from period -
quarter
: Extracted quarter from period (when applicable)
Additional columns may be present depending on the specific data series.
# Example of typical data structure
sample_data <- arad_get_data("SRUMD08402C")
#> Error in value[[3L]](cond): Failed to retrieve data from ARAD API: HTTP 400 Bad Request.
str(sample_data)
#> Error in eval(expr, envir, enclos): object 'sample_data' not found
API endpoints used
The package accesses these ARAD API endpoints:
-
/aradb/api/v1/data
- Time series data retrieval -
/aradb/api/v1/indicators
- Available indicators listing -
/aradb/api/v1/indicators-dims
- Indicator dimensional structure -
/aradb/api/v1/indicators-tree
- Hierarchical indicator tree structure
Next steps
- Explore the function reference for detailed documentation
- Check out additional examples in the articles section
- Visit the Czech National Bank ARAD website for more information about available data series
- Report issues or contribute at the GitHub repository