Introduction

This file is not education data itself — it’s the country reference table that sits behind the World Bank’s EdStats (Education Statistics) database. Every actual indicator table in EdStats (literacy rates, enrollment, spending, etc.) joins back to this file by CountryCode to know which region a country belongs to, what income group it’s classified in, which statistical standards it follows, and dozens of other metadata facts. Understood on its own, it’s a useful snapshot of how the World Bank organizes and classifies the world’s economies — 234 rows covering both individual countries and the regional/income aggregates used to summarize them.

# NOTE: the original World Bank export is ISO-8859-1 encoded. If you re-download
# the source file yourself, read it with locale(encoding = "ISO-8859-1") or
# convert to UTF-8 first (e.g. iconv -f ISO-8859-1 -t UTF-8) to avoid errors.
raw <- read_csv("EDSTATS_Country.csv", col_types = cols(.default = "c"))

# Rows with no Region are the aggregate/grouping rows (World, income groups,
# regional roll-ups) rather than individual countries.
countries   <- raw %>% filter(!is.na(Region))
aggregates  <- raw %>% filter(is.na(Region))

About the data

tibble(
  Metric = c("Total rows", "Individual countries/economies", "Regional & income-group aggregate rows",
             "Columns of metadata"),
  Value = c(nrow(raw), nrow(countries), nrow(aggregates), ncol(raw))
) %>%
  kable(caption = "Dataset snapshot") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Dataset snapshot
Metric Value
Total rows 234
Individual countries/economies 210
Regional & income-group aggregate rows 24
Columns of metadata 31

Of the 31 columns, most describe statistical methodology and reporting practices rather than economic outcomes: what year a country’s national accounts are based on, which System of National Accounts version it follows, whether it publishes to the IMF’s data dissemination standard, and when its most recent population census, household survey, or agricultural census took place. This makes the file most useful as a data-quality and comparability guide — a reminder that not every country’s statistics are collected the same way or as recently as others.


Regional and income coverage

region_income <- countries %>%
  count(Region, `Income Group`) %>%
  filter(!is.na(`Income Group`))

income_order <- c("Low income", "Lower middle income", "Upper middle income",
                   "High income: nonOECD", "High income: OECD")

ggplot(region_income %>% mutate(`Income Group` = factor(`Income Group`, levels = income_order)),
       aes(x = fct_reorder(Region, n, sum), y = n, fill = `Income Group`)) +
  geom_col() +
  coord_flip() +
  scale_fill_brewer(palette = "RdYlBu", direction = -1) +
  labs(title = "Countries by region and income group",
       x = NULL, y = "Number of countries", fill = "Income group") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom")

countries %>%
  count(Region, sort = TRUE) %>%
  mutate(share = percent(n / sum(n), accuracy = 0.1)) %>%
  kable(col.names = c("Region", "Countries", "Share"), caption = "Countries by World Bank region") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Countries by World Bank region
Region Countries Share
Europe & Central Asia 57 27.1%
Sub-Saharan Africa 47 22.4%
Latin America & Caribbean 38 18.1%
East Asia & Pacific 36 17.1%
Middle East & North Africa 21 10.0%
South Asia 8 3.8%
North America 3 1.4%

Europe & Central Asia (57 countries) and Sub-Saharan Africa (47) are the two largest regional groupings, together accounting for exactly half of all classified countries — a reflection of how many small post-Soviet and African states exist relative to other regions, not a statement about population or economic weight. Income classification skews toward the lower half: low, lower-middle, and upper-middle income countries together make up about 62% of classified economies, while OECD high-income countries are the smallest single group (30 countries).


Income group by region

countries %>%
  filter(!is.na(`Income Group`)) %>%
  count(Region, `Income Group`) %>%
  pivot_wider(names_from = `Income Group`, values_from = n, values_fill = 0) %>%
  kable(caption = "Income group composition of each region") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Income group composition of each region
Region High income: OECD High income: nonOECD Low income Lower middle income Upper middle income
East Asia & Pacific 4 8 5 15 4
Europe & Central Asia 23 12 2 7 13
Latin America & Caribbean 0 8 1 9 20
Middle East & North Africa 1 7 0 9 4
North America 2 1 0 0 0
South Asia 0 0 3 5 0
Sub-Saharan Africa 0 1 29 11 6

The regional/income cross-tabulation shows sharp structural differences: Sub-Saharan Africa is almost entirely low- and lower-middle income (no OECD high-income members at all), while Europe & Central Asia spans the full income spectrum, from low-income Central Asian states to some of the wealthiest OECD economies in the world — the most economically diverse region in the file. North America’s 3 members are entirely high-income, as expected.


World Bank lending category

lending_summary <- countries %>%
  mutate(`Lending category` = coalesce(`Lending category`, "Not applicable (high-income)")) %>%
  count(`Lending category`, sort = TRUE) %>%
  mutate(share = percent(n / sum(n), accuracy = 0.1))

lending_summary %>%
  kable(col.names = c("Lending Category", "Countries", "Share"),
        caption = "World Bank lending category") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
World Bank lending category
Lending Category Countries Share
Not applicable (high-income) 68 32.4%
IBRD 63 30.0%
IDA 63 30.0%
Blend 16 7.6%

The lending category identifies which arm of the World Bank Group a country borrows from: IBRD (International Bank for Reconstruction and Development) serves middle-income and creditworthy countries, IDA (International Development Association) serves the poorest countries with concessional financing, and Blend countries qualify for both. 63 countries fall into each of IBRD and IDA, with 16 “Blend” countries qualifying for both — and the 92 countries with no lending category are, almost entirely, high-income countries that don’t borrow from the Bank at all.


Statistical reporting standards

standards <- tibble(
  Standard = c("IMF Special Data Dissemination Standard (SDDS)",
               "IMF General Data Dissemination System (GDDS)",
               "System of National Accounts 1993",
               "Vital registration system complete"),
  `Countries reporting` = c(
    sum(countries$`IMF data dissemination standard` == "SDDS", na.rm = TRUE),
    sum(countries$`IMF data dissemination standard` == "GDDS", na.rm = TRUE),
    sum(countries$`System of National Accounts` == "1993", na.rm = TRUE),
    sum(countries$`Vital registration complete` == "Yes", na.rm = TRUE)
  )
)

standards %>%
  kable(caption = "Adoption of key international statistical standards") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Adoption of key international statistical standards
Standard Countries reporting
IMF Special Data Dissemination Standard (SDDS) 68
IMF General Data Dissemination System (GDDS) 95
System of National Accounts 1993 85
Vital registration system complete 103

These four fields are effectively a data-quality signal for every other World Bank indicator table: a country following the stricter SDDS standard, using the modern 1993 System of National Accounts, and maintaining complete vital registration is one whose statistics (education, health, economic) can generally be trusted more readily than a country reporting under the looser GDDS standard with an incomplete vital registration system. Only about half of countries with recorded values have a complete vital registration system — a reminder that even basic counts like births and deaths are not uniformly well-measured worldwide, let alone more complex education indicators like literacy or enrollment.

ppp_years <- countries %>%
  filter(!is.na(`PPP survey year`)) %>%
  count(`PPP survey year`)

ppp_years %>%
  kable(col.names = c("PPP Survey Year", "Countries"),
        caption = "Purchasing Power Parity (PPP) survey year") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Purchasing Power Parity (PPP) survey year
PPP Survey Year Countries
2005 145

Every country with a recorded PPP survey year in this file used the 2005 International Comparison Program round — meaning any purchasing-power-parity-adjusted figures drawing on this vintage of World Bank data share a common price-comparison baseline, which matters for anyone chaining PPP-adjusted indicators together across countries.


Regional and income aggregate rows

aggregates %>%
  select(CountryCode, `Short Name`) %>%
  kable(caption = "Non-country rows: regional and income-group aggregates used elsewhere in EdStats") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  scroll_box(height = "350px")
Non-country rows: regional and income-group aggregates used elsewhere in EdStats
CountryCode Short Name
EAP East Asia & Pacific (developing only)
EAS East Asia & Pacific (all income levels)
ECA Europe & Central Asia (developing only)
ECS Europe & Central Asia (all income levels)
EMU Euro area
HIC High income
HPC Heavily indebted poor countries (HIPC)
LAC Latin America & Caribbean (developing only)
LCN Latin America & Caribbean (all income levels)
LDC Least developed countries: UN classification
LIC Low income
LMC Lower middle income
LMY Low & middle income
MEA Middle East & North Africa (all income levels)
MIC Middle income
MNA Middle East & North Africa (developing only)
NAC North America
NOC High income: nonOECD
OEC High income: OECD
SAS South Asia
SSA Sub-Saharan Africa (developing only)
SSF Sub-Saharan Africa (all income levels)
UMC Upper middle income
WLD World

These 24 rows are not countries — they’re the codes (WLD for World, LIC for Low income, SSF for Sub-Saharan Africa “all income levels,” etc.) that the World Bank uses to report regional and income-group totals in the actual indicator tables. Some regions appear twice, once as “developing only” (e.g. SSA) and once as “all income levels” (e.g. SSF) — a distinction worth watching for when joining or filtering EdStats indicator data, since accidentally including both versions of the same region in a sum would double-count.


Explore the data

countries %>%
  select(CountryCode, `Short Name`, Region, `Income Group`, `Lending category`, `Currency Unit`) %>%
  datatable(options = list(pageLength = 15, scrollX = TRUE), rownames = FALSE, filter = "top")

Key takeaways

  • This file is metadata, not education outcomes — it classifies 210 countries and 24 aggregate regions/income groups, and every substantive EdStats indicator table depends on it for region and income context.
  • Europe & Central Asia and Sub-Saharan Africa are the two largest regional groups, together half of all classified countries, but they sit at opposite ends of the income spectrum — ECA spans the full range while SSA is almost entirely low- and lower-middle income.
  • World Bank lending category splits almost evenly between IBRD and IDA countries (63 each), with high-income countries (92 of them) falling outside the lending system entirely.
  • Statistical reporting quality varies substantially by country: adoption of the stricter SDDS standard, the modern System of National Accounts, and complete vital registration are far from universal, which is a useful caveat before treating any two countries’ indicator values as equally reliable.
  • Aggregate rows must be handled carefully: several regions appear in both “developing only” and “all income levels” versions, and mixing them in an analysis risks double-counting.

Limitations

This file captures a single snapshot in time of the World Bank’s country classifications — income group and region assignments are periodically revised (a country can move between income tiers as its economy grows), so this table should be treated as a specific vintage rather than a permanently fixed reference. It also contains no indicator values itself; any substantive claim about education outcomes requires joining this file to the actual EdStats indicator tables by CountryCode.


Report generated in R Markdown. To publish: put EDSTATS_Country.csv in the same folder as this file, open it in RStudio, click Knit, then use the Publish button (top right of the preview pane) to push directly to RPubs.