README
Source on GitHubHarmonize countries in the EBRD style. Available in Julia, R, Python, and Stata.
EBRDo takes a table with a country column (ISO2, ISO3, ISO-numeric, or country
name) and adds five columns that classify each country the way the European Bank for
Reconstruction and Development (EBRD) does. The same tool is available in all four
languages, generated from one source of truth and tested to give identical results.
# R
library(EBRDo)
ebrdo(data.frame(country = c("Kazakhstan", "Germany", "Kosovo", "United States")))
#> country ebrd_coo ebrd_name ebrd_region transition_group combined_group
#> 1 Kazakhstan 1 Kazakhstan Central Asia Central Asia <NA>
#> 2 Germany 0 Germany Advanced Europe Advanced Europe Advanced Europe
#> 3 Kosovo 1 Kosovo South-eastern Europe Western Balkans EBRD Emerging…
#> 4 United States 0 United States <NA> <NA> <NA>What it adds
| Column | Meaning |
|---|---|
ebrd_coo |
1 if the country is an EBRD Country of Operation, 0 otherwise, missing if unresolved |
ebrd_name |
EBRD-spelled English name (Czechia, Türkiye, Taipei China, Hong Kong SAR, West Bank and Gaza, …) |
ebrd_region |
Official EBRD region group (CEB, Central Asia, EEC, South-eastern Europe, SEMED, Türkiye, SSA) |
transition_group |
The grouping used in EBRD's Transition Report (EBRD-EU, Western Balkans, …) |
combined_group |
A single collapsed grouping (EBRD-EU / EBRD Emerging Europe / advanced / IMF EMMIEs / IMF LIDCs) |
Non-COO comparator groups (Advanced Europe, Advanced Economies, the IMF aggregates, EBRD Emerging Europe) can be placed alongside the EBRD groups, and are configurable. Ireland is always excluded from comparators, because multinational profit-shifting distorts its macro data. Selecting overlapping comparator groups raises an informative error.
The four ports
| Julia | R | Python | Stata | |
|---|---|---|---|---|
| Folder | julia/ |
r/ |
python/ |
stata/ |
| Works with | any Tables.jl table | data.frame, tibble, data.table, duckdb |
pandas DataFrame | the in-memory dataset |
| Harmonization engine | CountryCodes.jl | countrycode (CRAN) |
country_converter |
bundled crosswalk |
| Entry point | ebrdo(table, :col) |
df %>% ebrdo() |
ebrdo.ebrdo(df) |
ebrdo var |
One source of truth, verified parity
All ports derive their reference data from a single curated definition built on
countrycode/CountryCodes/country_converter. That definition covers the 41 Countries
of Operation, the EBRD/Transition/IMF groupings, the special spellings, and the Kosovo
handling. The Stata crosswalk and the Julia/R/Python lookup tables are all generated from
it. A cross-port parity test runs the same adversarial inputs (mixed schemes, accents,
whitespace, Kosovo aliases, numerics, unresolvable values) through the ports and confirms
they return identical classifications, value for value. None of them crash, and none
corrupt their input. (The Python port resolves names through country_converter; a few
non-COO fallback spellings can differ from countrycode — see python/README.md.)
Installation
Julia
using Pkg
Pkg.add(url = "https://github.com/angrahed/CountryCodes.jl") # dependency, until registered
Pkg.add(url = "https://github.com/angrahed/EBRDo", subdir = "julia")R
# install.packages("pak")
pak::pak("angrahed/EBRDo/r")
# or: remotes::install_github("angrahed/EBRDo", subdir = "r")Python
uv add "ebrdo @ git+https://github.com/angrahed/EBRDo#subdirectory=python"
# or: pip install "git+https://github.com/angrahed/EBRDo#subdirectory=python"Stata
The most reliable route ships the reference data: clone the repo and put stata/ on the adopath.
* git clone https://github.com/angrahed/EBRDo.git
adopath ++ "EBRDo/stata"
help ebrdonet install works for the program and help, but Stata treats the .dta reference data
as ancillary (not copied to the adopath), so the clone route above is recommended:
net install ebrdo, from("https://raw.githubusercontent.com/angrahed/EBRDo/main/stata") replace
* then fetch and place the datasets on your adopath (e.g. PERSONAL):
net get ebrdo, from("https://raw.githubusercontent.com/angrahed/EBRDo/main/stata") replaceQuick start
# Julia
using DataFrames, EBRDo
df = DataFrame(country = ["Kazakhstan", "Germany", "Kosovo"])
ebrdo(df, :country) # adds the five columns
is_ebrd_coo("Kazakhstan") # 1
ebrd_name("TUR") # "Türkiye"
ebrd_coos() # all 41 COO names, in reference order# R
library(EBRDo)
df <- data.frame(country = c("Kazakhstan", "Germany", "Kosovo"))
ebrdo(df) # country column auto-detected
ebrd_region(c("DEU", "POL"), comparators = "Advanced Economies")
ebrd_coos() # all 41 COO names, in reference order# Python
import pandas as pd, ebrdo
df = pd.DataFrame({"country": ["Kazakhstan", "Germany", "Kosovo"]})
ebrdo.ebrdo(df) # country column auto-detected
ebrdo.ebrd_name("TUR") # "Türkiye"
ebrdo.ebrd_coos() # all 41 COO names, in reference order* Stata
ebrdo country, comparators("Advanced Economies")Each port supports the same options (comparators, advanced, abbreviate, output
naming), documented in its folder's README and in the Julia/R/Stata help. Input is
matched case- and accent-insensitively; ISO2, ISO3, ISO-numeric, and name all resolve,
and Kosovo (which has no official ISO3) is accepted as KOS, XKX, XK, KV,
"Kosovo", and so on.
Repository layout
EBRDo/
├── julia/ EBRDo.jl Julia package (depends on CountryCodes.jl)
├── r/ EBRDo R package (CRAN-style; tibble/data.table/duckdb)
├── python/ ebrdo Python package (pandas; depends on country_converter)
├── stata/ ebrdo Stata package (ado + help + bundled crosswalk)
├── CITATION.cff
└── LICENSE (MIT)
Citing
See CITATION.cff, or cite as: Anton Grahed, EBRDo: Harmonize
countries in the EBRD style (Julia, R, and Stata), 2026.
Acknowledgements
Country code and name harmonization is powered by Vincent Arel-Bundock's
countrycode (R) and its Julia port
CountryCodes.jl; the Python port uses
country_converter.
License
MIT © Anton Grahed.