opennaijR is a reproducible macroeconomic data engineering framework for Africa. It gives you direct programmatic access to official economic data from central banks and national statistics bureaus – starting with Nigeria and expanding continent-wide. You ask for a dataset by name. opennaijR connects to the source, cleans the result, and returns a tidy, analysis-ready object. Every transformation is recorded so your work is fully reproducible from the moment data enters your workflow.
Getting Started
opennaijR helps you access Nigerian public data (like
inflation, exchange rates, GDP, etc.) in just three simple
steps:
- Load OpennaijR Package
- Discover what datasets are available
- Fetch the dataset you need
Let’s walk through this step-by-step.
Step 2: Discover Available Datasets
Think of discover_datasets() as a catalog of
datasets.
discover_datasets() shows you what Nigerian datasets are
available and where they come from — so you can decide what to analyze
next. Just like browsing a store before buying something, this function
shows you:
- Dataset names
- Dataset IDs
- Data source (e.g., CBN)
- Alternative names (aliases)
- Available variables (columns you can request)
Run:
## # A tibble: 21 × 5
## dataset_key dataset_id source aliases variables
## <chr> <chr> <chr> <chr> <chr>
## 1 inflation_ng cbn_inflation CBN inflati… headline…
## 2 exchange_rates cbn_exchange_rates CBN exchang… buying_r…
## 3 nfem_exchange_rates cbn_nfem_rates CBN nfem, n… closing,…
## 4 monthly_avg_exchange_rates cbn_monthly_avg_exchange CBN monthly… ifem_dol…
## 5 crude_oil cbn_crude_oil CBN crude o… price_bo…
## 6 daily_crude_oil cbn_daily_crude_oil CBN daily c… price_bo…
## 7 external_reserves cbn_external_reserves CBN externa… gross_re…
## 8 money_credit cbn_money_credit CBN money a… broad_mo…
## 9 money_market cbn_money_market CBN money m… interban…
## 10 interbank_rates cbn_interbank_rates CBN interba… rate_typ…
## # ℹ 11 more rows
To see the full list in R console use ’discover_datasets() |> print(n = Inf)`
Why This Is Important
Instead of guessing dataset names, you can:
- See what datasets exist
- Search by keyword
- Check what variables are available
Search for a Specific Dataset
If you’re looking for exchange rate data:
discover_datasets(dataset = "exchange")## # A tibble: 3 × 5
## dataset_key dataset_id source aliases variables
## <chr> <chr> <chr> <chr> <chr>
## 1 exchange_rates cbn_exchange_rates CBN exchange… buying_r…
## 2 nfem_exchange_rates cbn_nfem_rates CBN nfem, nf… closing,…
## 3 monthly_avg_exchange_rates cbn_monthly_avg_exchange CBN monthly … ifem_dol…
This filters the catalog to only datasets that match “exchange”.
Search Within a Specific Source
If you want to narrow your search to a particular data source (like CBN), you can combine source and dataset.
For example, to find inflation datasets from CBN only:
discover_datasets(source = "cbn", dataset = "inflation")## # A tibble: 1 × 5
## dataset_key dataset_id source aliases variables
## <chr> <chr> <chr> <chr> <chr>
## 1 inflation_ng cbn_inflation CBN inflation, inflation rates headline_yoy, he…
This tells opennaijR:
Look only inside the CBN source
Return datasets that match “inflation”
Step 3: Fetch Data
Once you know the dataset name, fetching data is very simple.
To get exchange rates from the Central Bank of Nigeria (CBN):
exchange_rates <- cbn("exchange_rates")## Fetching raw data from 'https://www.cbn.gov.ng/api/GetAllExchangeRates' ...
## Applying canonicalization using 'standardize_cbn_exchange'
## Creating new version '20260312T181854Z-39670'
## Writing to pin 'cbn__exchange_rates__d305a3e522e5ccc56286e414cfd231cd'
That’s it.
You now have the data stored in:
exchange_rates
What Happens Behind the Scenes?
When you run:
cbn("exchange_rates")## 📦 Loading cached CBN data from pins
## <opennaijR table>
## Rows: 60500 Columns: 5
##
## currency buying_rate central_rate selling_rate date
## 1 CFA 2.4088 2.4188 2.4288 2026-03-12
## 2 YUAN/RENMINBI 199.5205 199.5933 199.6661 2026-03-12
## 3 DANISH KRONA 211.5044 211.5816 211.6587 2026-03-12
## 4 EURO 1580.7420 1581.3187 1581.8954 2026-03-12
## 5 YEN 8.6201 8.6232 8.6264 2026-03-12
## 6 RIYAL 365.1859 365.3192 365.4524 2026-03-12
## 7 SOUTH AFRICAN RAND 82.3226 82.3526 82.3826 2026-03-12
## 8 SWISS FRANC 1751.6696 1752.3087 1752.9477 2026-03-12
## 9 POUNDS STERLING 1833.4633 1834.1322 1834.8011 2026-03-12
## 10 US DOLLAR 1370.5063 1371.0063 1371.5063 2026-03-12
opennaijR automatically:
- Builds a data request
- Checks if you already downloaded it before (cache system)
- Downloads fresh data if needed
- Cleans and standardizes the data
- Saves it for faster reuse next time
So next time you run the same request, it loads instantly.
You don’t need to manage any of this manually.
Optional: Filter Your Data
You can refine your request.
Select specific variables:
## Fetching raw data from 'https://www.cbn.gov.ng/api/GetAllExchangeRates' ...
## Applying canonicalization using 'standardize_cbn_exchange'
## Creating new version '20260312T181855Z-3b08f'
## Writing to pin 'cbn__exchange_rates__3be8261f4f13056b9a63ec5304c99646'
## <opennaijR table>
## Rows: 60500 Columns: 2
##
## currency buying_rate
## 1 CFA 2.4088
## 2 YUAN/RENMINBI 199.5205
## 3 DANISH KRONA 211.5044
## 4 EURO 1580.7420
## 5 YEN 8.6201
## 6 RIYAL 365.1859
## 7 SOUTH AFRICAN RAND 82.3226
## 8 SWISS FRANC 1751.6696
## 9 POUNDS STERLING 1833.4633
## 10 US DOLLAR 1370.5063
Select a date range:
cbn("exchange_rates", from = "2020-01-01", to = "2023-12-31")## Fetching raw data from 'https://www.cbn.gov.ng/api/GetAllExchangeRates' ...
## Applying canonicalization using 'standardize_cbn_exchange'
## Creating new version '20260312T181857Z-39670'
## Writing to pin 'cbn__exchange_rates__2e6bdf4cdb0fbe97c9a08bf8ce123481'
## <opennaijR table>
## Rows: 60500 Columns: 5
##
## currency buying_rate central_rate selling_rate date
## 1 CFA 2.4088 2.4188 2.4288 2026-03-12
## 2 YUAN/RENMINBI 199.5205 199.5933 199.6661 2026-03-12
## 3 DANISH KRONA 211.5044 211.5816 211.6587 2026-03-12
## 4 EURO 1580.7420 1581.3187 1581.8954 2026-03-12
## 5 YEN 8.6201 8.6232 8.6264 2026-03-12
## 6 RIYAL 365.1859 365.3192 365.4524 2026-03-12
## 7 SOUTH AFRICAN RAND 82.3226 82.3526 82.3826 2026-03-12
## 8 SWISS FRANC 1751.6696 1752.3087 1752.9477 2026-03-12
## 9 POUNDS STERLING 1833.4633 1834.1322 1834.8011 2026-03-12
## 10 US DOLLAR 1370.5063 1371.0063 1371.5063 2026-03-12
Summary
| Task | Function |
|---|---|
| See available datasets | discover_manifest() |
| Search for a dataset | discover_manifest(dataset = "keyword") |
| Fetch CBN data | cbn("dataset_name") |
| Filter by date |
from, to
|
| Select columns | variables |
Mental Model
Think of opennaijR like this:
-
discover_datasets()→ Browse the data catalog -
cbn()“192” Download the dataset you want
Simple. Clean. Nigerian data made accessible.
Filter and Project Data (Clean and Focus)
After fetching a dataset, it often contains:
- Many rows
- Many columns
But most times, you don’t need everything.
You may want to:
- Filter to specific rows (e.g., only USD)
- Keep only certain columns
- Rename them to something cleaner
- Reorder them for reporting
- Document why you did this
That’s what apply_projection() is for.
Think of it as:
Filtering and reshaping your dataset for your specific task.
Example: Focus Only on US Dollar Exchange Rates
First, suppose we already fetched exchange rates:
exchange_rates <- cbn("exchange_rates")## 📦 Loading cached CBN data from pins
Now we will:
- Keep only US Dollar
- Select important columns
- Rename them
- Reorder them
- Record our reason
All in one step:
usd_rates <- apply_projection(
exchange_rates,
filter = currency == "US DOLLAR",
cols = c("date", "currency", "buying_rate", "central_rate", "selling_rate"),
rename = c(
buying = "buying_rate",
central = "central_rate",
selling = "selling_rate"
),
order = c("date", "currency", "buying", "central", "selling"),
reason = "Focus on USD rates"
)What Just Happened?
Let’s break it down in simple terms:
| Argument | What It Does |
|---|---|
filter |
Keeps only rows matching a condition |
cols |
Keeps only selected columns |
rename |
Gives columns cleaner names |
order |
Rearranges column order |
reason |
Records why you made this transformation |
So instead of technical column names like:
ratedate
buying_rate
central_rate
You now have clean, readable names:
date
buying
central
selling
View the Result
head(usd_rates)## <opennaijR table>
## Rows: 6 Columns: 5
##
## date currency buying central selling
## 10 2026-03-12 US DOLLAR 1370.506 1371.006 1371.506
## 23 2026-03-11 US DOLLAR 1375.193 1375.693 1376.193
## 36 2026-03-10 US DOLLAR 1400.401 1400.901 1401.401
## 49 2026-03-09 US DOLLAR 1392.256 1392.756 1393.256
## 62 2026-03-06 US DOLLAR 1392.256 1392.756 1393.256
## 75 2026-03-05 US DOLLAR 1386.447 1386.947 1387.447
Now your dataset is:
- Focused (USD only)
- Clean
- Easy to read
- Ready for plotting or reporting
Why apply_projection() Is Special
Unlike normal filtering or column selection, this function:
cat(“705 Done!”) Keeps the opennaijR_tbl class cat(“705
Done!”) Tracks what you changed cat(“705 Done!”) Saves a transformation
history
You can inspect the history:
attr(usd_rates, "projection_manifest")## [[1]]
## [[1]]$timestamp
## [1] "2026-03-12 18:18:57 UTC"
##
## [[1]]$action
## [1] "apply_projection"
##
## [[1]]$filter
## [1] "~currency == \"US DOLLAR\""
##
## [[1]]$kept
## [1] "date" "currency" "buying_rate" "central_rate" "selling_rate"
##
## [[1]]$renamed
## buying central selling
## "buying_rate" "central_rate" "selling_rate"
##
## [[1]]$ordered
## [1] "date" "currency" "buying" "central" "selling"
##
## [[1]]$reason
## [1] "Focus on USD rates"
This shows:
- When the transformation happened
- What filter was applied
- What columns were kept
- What was renamed
- The reason you provided
That makes your analysis transparent and reproducible.
Derive a New Measure (Create Insight)
After filtering and cleaning your data, the next step is often to create new variables.
For example:
- Year-on-year change
- Month-to-month change
- Percentage growth
- Gaps between variables
- Ratios
That’s what derive_measure() is for.
Think of it as:
Creating new economic indicators from existing data.
Example: Compute Percentage Change in USD Rates
Suppose we already prepared our dataset:
usd_rates
Now we want to compute the percentage change in exchange rates.
We can do:
usd_change <- derive_measure(
usd_rates,
pct_change = (buying - lag(buying)) / lag(buying) * 100,
reason = "Compute daily percentage change in USD buying rate"
)head(usd_rates)
What Just Happened?
Let’s break it down:
| Component | What It Does |
|---|---|
pct_change = ... |
Creates a new column |
lag(buying) |
Uses previous value |
* 100 |
Converts to percentage |
reason |
Documents why we created it |
So now your dataset contains a new column:
pct_change
That tells you how much the USD rate changed compared to the previous period.
View the Result
head(usd_change)## <opennaijR table>
## Rows: 6 Columns: 6
##
## date currency buying central selling pct_change
## 10 2026-03-12 US DOLLAR 1370.506 1371.006 1371.506 0
## 23 2026-03-11 US DOLLAR 1375.193 1375.693 1376.193 0
## 36 2026-03-10 US DOLLAR 1400.401 1400.901 1401.401 0
## 49 2026-03-09 US DOLLAR 1392.256 1392.756 1393.256 0
## 62 2026-03-06 US DOLLAR 1392.256 1392.756 1393.256 0
## 75 2026-03-05 US DOLLAR 1386.447 1386.947 1387.447 0
You now have:
- Original exchange rate columns
- A new derived column (
pct_change) - A recorded derivation history
Why derive_measure() Is Special
Unlike just writing:
usd_rates$pct_change <- ...
cat(“705 Done!”) Keeps the opennaijR_tbl class cat(“705
Done!”) racks the expression used cat(“705 Done!”) Records when it was
created cat(“705 Done!”) Stores your reason
You can inspect the derivation history:
attr(usd_change, "derive_manifest")## [[1]]
## [[1]]$timestamp
## [1] "2026-03-12 18:18:57 UTC"
##
## [[1]]$action
## [1] "derive_measure"
##
## [[1]]$derived
## [1] "pct_change"
##
## [[1]]$expressions
## pct_change
## "~(buying - lag(buying))/lag(buying) * 100"
##
## [[1]]$reason
## [1] "Compute daily percentage change in USD buying rate"
This makes your analysis:
- Transparent
- Reproducible
- Auditable
Very important for economic research.
You Can Derive Multiple Measures at Once
usd_extended <- derive_measure(
usd_rates,
pct_change = (buying - lag(buying)) / lag(buying) * 100,
spread = selling - buying,
reason = "Analyze volatility and bid-ask spread"
)Now you created:
- Percentage change
- Bid-ask spread
In one clean step.