Packages used
library(haven)
library(dplyr)
library(ggplot2)
library(tidyr)
library(broom)
library(knitr)
library(countrycode)Empirical Evidence from the Penn World Tables
The Solow-Swan model makes one of the most striking predictions in development economics: absolute convergence. According to this model, poor countries should grow faster than rich countries because of diminishing returns to capital, leading all economies to eventually converge to the same level of income per capita.
This prediction emerges from two key assumptions:
The mathematical intuition is straightforward: if the marginal product of capital is higher in poor countries (due to lower capital stock), then investment should flow there, generating higher growth rates until all countries reach the same steady state.
But does this prediction hold in reality? In this session’s exercise, you were asked to test the absolute convergence hypothesis using real-world data from the Penn World Tables. Below you find a possible solution for this exercise.
We test absolute convergence by estimating the following regression:
\[\frac{1}{T} \ln\left(\frac{y_{i,t+T}}{y_{i,t}}\right) = \alpha + \beta \ln(y_{i,t}) + \epsilon_i\]
Where:
Absolute convergence occurs if \(\beta < 0\): countries with lower initial income grow faster.
We use data from the Penn World Tables 11.0, which provides internationally comparable GDP data using purchasing power parity (PPP) adjustments.
We first import the PWT data, select the years of interest and define the list of OECD countries.
# Load Penn World Tables data
pwt_data <- read_dta("pwt110.dta") %>%
filter(year %in% c(1960, 1990, 2022), pop>1) %>%
select(c("countrycode", "country", "year", "cgdpo"))
# Create OECD country list for subset analysis
oecd_countries <- c(
"AUS", "AUT", "BEL", "CAN", "CHL", "CZE", "DNK", "EST",
"FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ISR",
"ITA", "JPN", "KOR", "LVA", "LTU", "LUX", "MEX", "NLD",
"NZL", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE",
"CHE", "TUR", "GBR", "USA")
# Display sample of data
kable(head(pwt_data, 5), caption = "Sample of Penn World Tables Data")| countrycode | country | year | cgdpo |
|---|---|---|---|
| AGO | Angola | 1990 | 41716.39 |
| AGO | Angola | 2022 | 225903.91 |
| ALB | Albania | 1990 | 12227.74 |
| ALB | Albania | 2022 | 43686.69 |
| ARE | United Arab Emirates | 1990 | 300576.81 |
Then we create the data set used for the estimation by transforming it into the right shape, filter for missing observations and calculating the necessary variables (such as annual growth rates, initial GDP)
# Create convergence dataset
convergence_data <- pwt_data %>%
pivot_wider(
names_from = year,
values_from = cgdpo,
names_prefix = "gdp_"
) %>%
filter(
!is.na(gdp_1960),
!is.na(gdp_1990),
!is.na(gdp_2022)
) %>%
mutate(
# Calculate annual growth rates (in decimal form)
growth_60_90 = (log(gdp_1990) - log(gdp_1960)) / 30,
growth_90_22 = (log(gdp_2022) - log(gdp_1990)) / 32,
growth_60_22 = (log(gdp_2022) - log(gdp_1960)) / 62,
# Initial GDP (log)
ln_gdp_1960 = log(gdp_1960),
ln_gdp_1990 = log(gdp_1990),
# Create OECD indicator
oecd = ifelse(countrycode %in% oecd_countries, "OECD", "Non-OECD")
)
# Display summary statistics
kable(convergence_data %>%
select(
country, gdp_1960, gdp_1990,
gdp_2022, growth_60_90, growth_90_22) %>%
head(10),
digits = 3,
caption = "Sample Countries: GDP Levels and Growth Rates")| country | gdp_1960 | gdp_1990 | gdp_2022 | growth_60_90 | growth_90_22 |
|---|---|---|---|---|---|
| Argentina | 71913.469 | 219936.453 | 1260669.75 | 0.037 | 0.055 |
| Australia | 178392.688 | 554314.625 | 1703845.00 | 0.038 | 0.035 |
| Austria | 78335.203 | 223089.672 | 581060.31 | 0.035 | 0.030 |
| Burundi | 2097.166 | 5712.411 | 13065.02 | 0.033 | 0.026 |
| Belgium | 104181.156 | 281506.406 | 665497.25 | 0.033 | 0.027 |
| Benin | 4094.783 | 7253.897 | 46482.14 | 0.019 | 0.058 |
| Burkina Faso | 5438.738 | 10643.562 | 52374.13 | 0.022 | 0.050 |
| Bangladesh | 94496.164 | 181639.328 | 1327167.88 | 0.022 | 0.062 |
| Bolivia (Plurinational State of) | 6382.087 | 17126.891 | 114655.68 | 0.033 | 0.059 |
| Brazil | 177550.828 | 1006764.188 | 3826745.25 | 0.058 | 0.042 |
We then test convergence for the different time horizons and country groups.
Table 1 summarizes the result of estimating the convergence regression for 1960-1990 for all countries (see also Figure 1).
model_60_90_all <- lm(growth_60_90 ~ ln_gdp_1960, data = convergence_data)
# Extract results for the summary table below
results_60_90_all <- tidy(model_60_90_all)
r_squared_60_90_all <- glance(model_60_90_all)$r.squared
# Display results
kable(results_60_90_all, digits = 4,
caption = "Convergence Regression Results: All Countries (1960-1990)")| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| (Intercept) | 0.0361 | 0.0129 | 2.7999 | 0.0063 |
| ln_gdp_1960 | 0.0003 | 0.0012 | 0.2773 | 0.7822 |
all_6090_plot <- ggplot(convergence_data, aes(x = exp(ln_gdp_1960), y = growth_60_90 * 100)) +
geom_point(aes(color = oecd), alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
scale_color_manual(values = c("OECD" = "#1f77b4", "Non-OECD" = "#ff7f0e")) +
labs(
title = "Test of Absolute Convergence: All Countries (1960-1990)",
subtitle = paste0("β = ", round(results_60_90_all$estimate[2], 4),
", R² = ", round(r_squared_60_90_all, 3)),
x = "GDP per capita in 1960 (log scale, PPP)",
y = "Average Annual Growth Rate 1960-1990 (%)",
color = "Country Group",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
all_6090_plot
If we restrict ourselves to the subset of OECD countries we get the result summarized in Table 2 (see also Figure 2):
# Filter for OECD countries
convergence_oecd <- convergence_data %>% filter(oecd == "OECD")
# Convergence regression for OECD countries
model_60_90_oecd <- lm(growth_60_90 ~ ln_gdp_1960, data = convergence_oecd)
# Extract results
results_60_90_oecd <- tidy(model_60_90_oecd)
r_squared_60_90_oecd <- glance(model_60_90_oecd)$r.squared
# Display results
kable(results_60_90_oecd, digits = 4,
caption = "Convergence Regression Results: OECD Countries (1960-1990)")| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| (Intercept) | 0.0669 | 0.0272 | 2.4626 | 0.0214 |
| ln_gdp_1960 | -0.0021 | 0.0023 | -0.9337 | 0.3597 |
oecd_6090_plot <- ggplot(
data = convergence_oecd,
mapping = aes(
x = exp(ln_gdp_1960),
y = growth_60_90 * 100)
) +
geom_point(color = "#1f77b4", alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
labs(
title = "Test of Absolute Convergence: OECD Countries (1960-1990)",
subtitle = paste0("β = ", round(results_60_90_oecd$estimate[2], 4),
", R² = ", round(r_squared_60_90_oecd, 3)),
x = "GDP per capita in 1960 (log scale, PPP)",
y = "Average Annual Growth Rate 1960-1990 (%)",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
oecd_6090_plot
Below you find the code for the other cases:
# Convergence regression for 1990-2022 (all countries)
model_90_22_all <- lm(growth_90_22 ~ ln_gdp_1990, data = convergence_data)
# Extract results
results_90_22_all <- tidy(model_90_22_all)
r_squared_90_22_all <- glance(model_90_22_all)$r.squared
# Display results
# kable(results_90_22_all, digits = 4,
# caption = "Convergence Regression Results: All Countries (1990-2022)")all_9022 <- ggplot(
data = convergence_data,
mapping = aes(x = exp(ln_gdp_1990), y = growth_90_22 * 100)
) +
geom_point(aes(color = oecd), alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
scale_color_manual(values = c("OECD" = "#1f77b4", "Non-OECD" = "#ff7f0e")) +
labs(
title = "Test of Absolute Convergence: All Countries (1990-2022)",
subtitle = paste0("β = ", round(results_90_22_all$estimate[2], 4),
", R² = ", round(r_squared_90_22_all, 3)),
x = "GDP per capita in 1990 (log scale, PPP)",
y = "Average Annual Growth Rate 1990-2022 (%)",
color = "Country Group",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)# Convergence regression for OECD countries
model_90_22_oecd <- lm(growth_90_22 ~ ln_gdp_1990, data = convergence_oecd)
# Extract results
results_90_22_oecd <- tidy(model_90_22_oecd)
r_squared_90_22_oecd <- glance(model_90_22_oecd)$r.squared
# Display results
# kable(results_90_22_oecd, digits = 4,
# caption = "Convergence Regression Results: OECD Countries (1990-2022)")oecd9022_plot <- ggplot(
data = convergence_oecd,
mapping = aes(x = exp(ln_gdp_1990), y = growth_90_22 * 100)
) +
geom_point(color = "#1f77b4", alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
labs(
title = "Test of Absolute Convergence: OECD Countries (1990-2022)",
subtitle = paste0("β = ", round(results_90_22_oecd$estimate[2], 4),
", R² = ", round(r_squared_90_22_oecd, 3)),
x = "GDP per capita in 1990 (log scale, PPP)",
y = "Average Annual Growth Rate 1990-2022 (%)",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)Table 3 provides a summary of our convergence test results.
summary_results <- data.frame(
Period = c("1960-1990", "1960-1990", "1990-2022", "1990-2022"),
Sample = c("All Countries", "OECD Only", "All Countries", "OECD Only"),
Beta = c(
round(results_60_90_all$estimate[2], 4),
round(results_60_90_oecd$estimate[2], 4),
round(results_90_22_all$estimate[2], 4),
round(results_90_22_oecd$estimate[2], 4)
),
P_value = c(
round(results_60_90_all$p.value[2], 4),
round(results_60_90_oecd$p.value[2], 4),
round(results_90_22_all$p.value[2], 4),
round(results_90_22_oecd$p.value[2], 4)
),
R_squared = c(
round(r_squared_60_90_all, 3),
round(r_squared_60_90_oecd, 3),
round(r_squared_90_22_all, 3),
round(r_squared_90_22_oecd, 3)
),
Convergence = c(
ifelse(
results_60_90_all$estimate[2] < 0 & results_60_90_all$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_60_90_oecd$estimate[2] < 0 & results_60_90_oecd$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_90_22_all$estimate[2] < 0 & results_90_22_all$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_90_22_oecd$estimate[2] < 0 & results_90_22_oecd$p.value[2] < 0.05,
"Yes", "No")
)
)
kable(summary_results,
caption = "Summary of Convergence Test Results",
col.names = c("Period", "Sample", "β (Convergence Parameter)",
"P-value", "R²", "Significant Convergence?"))| Period | Sample | β (Convergence Parameter) | P-value | R² | Significant Convergence? |
|---|---|---|---|---|---|
| 1960-1990 | All Countries | 0.0003 | 0.7822 | 0.001 | No |
| 1960-1990 | OECD Only | -0.0021 | 0.3597 | 0.035 | No |
| 1990-2022 | All Countries | -0.0027 | 0.0581 | 0.040 | No |
| 1990-2022 | OECD Only | -0.0050 | 0.0078 | 0.260 | Yes |
Solow-Swan Prediction:
Our Results:
Why is it that absolute convergence is not happening as predicted by Solow-Swan? The great thing about such models is that we can systematically think about which of its assumptions might not hold:
The weak evidence for absolute convergence has led economists to focus on conditional convergence - the idea that countries converge to their own steady states, which may differ based on:
As you see, this addresses some of the possible explanations above. Other economists, especially those working in Marxist and Dependency Theory traditions would be even more skeptical, and argue for a systematic relationship between development and underdevelopment, suggesting that studying conditional convergence is not a fruitful endeavor either.
These findings have important implications for development policy:
Your empirical test of the Solow model’s convergence prediction illustrates the complexity of real-world development. While you found some evidence of convergence among similar countries (like OECD members), the prediction of universal convergence does not hold for the global economy.
This doesn’t mean the Solow model is wrong - rather, it highlights that the assumptions of identical technology, institutions, and preferences across countries are often violated in reality. The model remains valuable for understanding growth mechanics, but must be complemented with theories that account for institutional, technological, and structural differences between countries.
Understanding these limitations is crucial for development economists and policymakers who seek to design effective strategies for promoting economic growth and reducing global inequality.
---
title: "Testing Absolute Convergence: The Solow Model's Key Prediction"
subtitle: "Empirical Evidence from the Penn World Tables"
format:
html:
toc: true
code-fold: true
fig-width: 10
fig-height: 6
fig-cap-location: top
tbl-cap-location: top
execute:
warning: false
message: false
---
# Introduction
The Solow-Swan model makes one of the most striking predictions in development economics: **absolute convergence**. According to this model, poor countries should grow faster than rich countries because of diminishing returns to capital, leading all economies to eventually converge to the same level of income per capita.
This prediction emerges from two key assumptions:
1. **Diminishing returns to capital**: As countries accumulate more capital, additional units of capital become less productive
2. **Factor mobility**: Capital and technology can flow freely between countries
The mathematical intuition is straightforward: if the marginal product of capital is higher in poor countries (due to lower capital stock), then investment should flow there, generating higher growth rates until all countries reach the same steady state.
But does this prediction hold in reality? In this session's exercise, you were asked to test the absolute convergence hypothesis using real-world data from the Penn World Tables. Below you find a *possible* solution for this exercise.
## The Convergence Test
We test absolute convergence by estimating the following regression:
$$\frac{1}{T} \ln\left(\frac{y_{i,t+T}}{y_{i,t}}\right) = \alpha + \beta \ln(y_{i,t}) + \epsilon_i$$
Where:
- $\frac{1}{T} \ln\left(\frac{y_{i,t+T}}{y_{i,t}}\right)$ is the average annual growth rate of GDP per capita over period T
- $y_{i,t}$ is initial GDP per capita
- $\beta$ is the convergence parameter
**Absolute convergence** occurs if $\beta < 0$: countries with lower initial income grow faster.
# Data and Setup
We use data from the Penn World Tables 11.0, which provides internationally comparable GDP data using purchasing power parity (PPP) adjustments.
```{r setup}
#| code-summary: "Packages used"
library(haven)
library(dplyr)
library(ggplot2)
library(tidyr)
library(broom)
library(knitr)
library(countrycode)
```
We first import the PWT data, select the years of interest and define the list of OECD countries.
```{r data-loading}
# Load Penn World Tables data
pwt_data <- read_dta("pwt110.dta") %>%
filter(year %in% c(1960, 1990, 2022), pop>1) %>%
select(c("countrycode", "country", "year", "cgdpo"))
# Create OECD country list for subset analysis
oecd_countries <- c(
"AUS", "AUT", "BEL", "CAN", "CHL", "CZE", "DNK", "EST",
"FIN", "FRA", "DEU", "GRC", "HUN", "ISL", "IRL", "ISR",
"ITA", "JPN", "KOR", "LVA", "LTU", "LUX", "MEX", "NLD",
"NZL", "NOR", "POL", "PRT", "SVK", "SVN", "ESP", "SWE",
"CHE", "TUR", "GBR", "USA")
# Display sample of data
kable(head(pwt_data, 5), caption = "Sample of Penn World Tables Data")
```
Then we create the data set used for the estimation by transforming it into the right shape, filter for missing observations and calculating the necessary variables
(such as annual growth rates, initial GDP)
```{r data-preparation}
# Create convergence dataset
convergence_data <- pwt_data %>%
pivot_wider(
names_from = year,
values_from = cgdpo,
names_prefix = "gdp_"
) %>%
filter(
!is.na(gdp_1960),
!is.na(gdp_1990),
!is.na(gdp_2022)
) %>%
mutate(
# Calculate annual growth rates (in decimal form)
growth_60_90 = (log(gdp_1990) - log(gdp_1960)) / 30,
growth_90_22 = (log(gdp_2022) - log(gdp_1990)) / 32,
growth_60_22 = (log(gdp_2022) - log(gdp_1960)) / 62,
# Initial GDP (log)
ln_gdp_1960 = log(gdp_1960),
ln_gdp_1990 = log(gdp_1990),
# Create OECD indicator
oecd = ifelse(countrycode %in% oecd_countries, "OECD", "Non-OECD")
)
# Display summary statistics
kable(convergence_data %>%
select(
country, gdp_1960, gdp_1990,
gdp_2022, growth_60_90, growth_90_22) %>%
head(10),
digits = 3,
caption = "Sample Countries: GDP Levels and Growth Rates")
```
# Testing Absolute Convergence
We then test convergence for the different time horizons and country groups.
@tbl-6090all summarizes the result of estimating the convergence regression for 1960-1990 for all countries (see also @fig-6090all).
```{r}
#| label: tbl-6090all
#| code-summary: "Convergence regression for 1960-1990 (all countries)"
#| tbl-cap: "Convergence regression for 1960-1990 (all countries)"
model_60_90_all <- lm(growth_60_90 ~ ln_gdp_1960, data = convergence_data)
# Extract results for the summary table below
results_60_90_all <- tidy(model_60_90_all)
r_squared_60_90_all <- glance(model_60_90_all)$r.squared
# Display results
kable(results_60_90_all, digits = 4,
caption = "Convergence Regression Results: All Countries (1960-1990)")
```
```{r}
#| label: "fig-6090all"
#| fig-cap: "Absolute Convergence Test: All Countries (1960-1990)"
#| code-summary: "Code for Figure 1"
all_6090_plot <- ggplot(convergence_data, aes(x = exp(ln_gdp_1960), y = growth_60_90 * 100)) +
geom_point(aes(color = oecd), alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
scale_color_manual(values = c("OECD" = "#1f77b4", "Non-OECD" = "#ff7f0e")) +
labs(
title = "Test of Absolute Convergence: All Countries (1960-1990)",
subtitle = paste0("β = ", round(results_60_90_all$estimate[2], 4),
", R² = ", round(r_squared_60_90_all, 3)),
x = "GDP per capita in 1960 (log scale, PPP)",
y = "Average Annual Growth Rate 1960-1990 (%)",
color = "Country Group",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
all_6090_plot
```
If we restrict ourselves to the subset of OECD countries we get the result summarized in @tbl-6090oecd (see also @fig-6090oecd):
```{r}
#| label: tbl-6090oecd
#| code-summary: "Convergence regression for 1960-1990 (OECD countries)"
#| tbl-cap: "Convergence regression for 1960-1990 (OECD countries)"
# Filter for OECD countries
convergence_oecd <- convergence_data %>% filter(oecd == "OECD")
# Convergence regression for OECD countries
model_60_90_oecd <- lm(growth_60_90 ~ ln_gdp_1960, data = convergence_oecd)
# Extract results
results_60_90_oecd <- tidy(model_60_90_oecd)
r_squared_60_90_oecd <- glance(model_60_90_oecd)$r.squared
# Display results
kable(results_60_90_oecd, digits = 4,
caption = "Convergence Regression Results: OECD Countries (1960-1990)")
```
```{r}
#| label: "fig-6090oecd"
#| fig-cap: "Absolute Convergence Test: OECD Countries (1960-1990)"
#| code-summary: "Code for Figure 2"
oecd_6090_plot <- ggplot(
data = convergence_oecd,
mapping = aes(
x = exp(ln_gdp_1960),
y = growth_60_90 * 100)
) +
geom_point(color = "#1f77b4", alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
labs(
title = "Test of Absolute Convergence: OECD Countries (1960-1990)",
subtitle = paste0("β = ", round(results_60_90_oecd$estimate[2], 4),
", R² = ", round(r_squared_60_90_oecd, 3)),
x = "GDP per capita in 1960 (log scale, PPP)",
y = "Average Annual Growth Rate 1960-1990 (%)",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
oecd_6090_plot
```
Below you find the code for the other cases:
```{r convergence-90-22-all}
#| code-summary: "Convergence regression for 1990-2022 (all countries)"
# Convergence regression for 1990-2022 (all countries)
model_90_22_all <- lm(growth_90_22 ~ ln_gdp_1990, data = convergence_data)
# Extract results
results_90_22_all <- tidy(model_90_22_all)
r_squared_90_22_all <- glance(model_90_22_all)$r.squared
# Display results
# kable(results_90_22_all, digits = 4,
# caption = "Convergence Regression Results: All Countries (1990-2022)")
```
```{r}
#| label: "fig-9022all"
#| fig-cap: "Absolute Convergence Test: All Countries (1990-2022)"
#| code-summary: "Code for Figure 3"
all_9022 <- ggplot(
data = convergence_data,
mapping = aes(x = exp(ln_gdp_1990), y = growth_90_22 * 100)
) +
geom_point(aes(color = oecd), alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
scale_color_manual(values = c("OECD" = "#1f77b4", "Non-OECD" = "#ff7f0e")) +
labs(
title = "Test of Absolute Convergence: All Countries (1990-2022)",
subtitle = paste0("β = ", round(results_90_22_all$estimate[2], 4),
", R² = ", round(r_squared_90_22_all, 3)),
x = "GDP per capita in 1990 (log scale, PPP)",
y = "Average Annual Growth Rate 1990-2022 (%)",
color = "Country Group",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
```
```{r convergence-90-22-oecd}
#| code-summary: "Convergence regression for 1990-2022 (OECD countries)"
# Convergence regression for OECD countries
model_90_22_oecd <- lm(growth_90_22 ~ ln_gdp_1990, data = convergence_oecd)
# Extract results
results_90_22_oecd <- tidy(model_90_22_oecd)
r_squared_90_22_oecd <- glance(model_90_22_oecd)$r.squared
# Display results
# kable(results_90_22_oecd, digits = 4,
# caption = "Convergence Regression Results: OECD Countries (1990-2022)")
```
```{r}
#| label: "fig-9022oecd"
#| fig-cap: "Absolute Convergence Test: OECD Countries (1990-2022)"
#| code-summary: "Code for Figure 4"
oecd9022_plot <- ggplot(
data = convergence_oecd,
mapping = aes(x = exp(ln_gdp_1990), y = growth_90_22 * 100)
) +
geom_point(color = "#1f77b4", alpha = 0.7, size = 3) +
geom_smooth(method = "lm", se = TRUE, color = "#E63946", linewidth = 1.2) +
scale_x_log10(labels = scales::dollar_format()) +
labs(
title = "Test of Absolute Convergence: OECD Countries (1990-2022)",
subtitle = paste0("β = ", round(results_90_22_oecd$estimate[2], 4),
", R² = ", round(r_squared_90_22_oecd, 3)),
x = "GDP per capita in 1990 (log scale, PPP)",
y = "Average Annual Growth Rate 1990-2022 (%)",
caption = "Negative slope indicates convergence"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12)
)
```
# Summary and Interpretation
## Summary of the findings
@tbl-summary provides a summary of our convergence test results.
```{r}
#| code-summary: "Code for the summary table"
#| label: tbl-summary
summary_results <- data.frame(
Period = c("1960-1990", "1960-1990", "1990-2022", "1990-2022"),
Sample = c("All Countries", "OECD Only", "All Countries", "OECD Only"),
Beta = c(
round(results_60_90_all$estimate[2], 4),
round(results_60_90_oecd$estimate[2], 4),
round(results_90_22_all$estimate[2], 4),
round(results_90_22_oecd$estimate[2], 4)
),
P_value = c(
round(results_60_90_all$p.value[2], 4),
round(results_60_90_oecd$p.value[2], 4),
round(results_90_22_all$p.value[2], 4),
round(results_90_22_oecd$p.value[2], 4)
),
R_squared = c(
round(r_squared_60_90_all, 3),
round(r_squared_60_90_oecd, 3),
round(r_squared_90_22_all, 3),
round(r_squared_90_22_oecd, 3)
),
Convergence = c(
ifelse(
results_60_90_all$estimate[2] < 0 & results_60_90_all$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_60_90_oecd$estimate[2] < 0 & results_60_90_oecd$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_90_22_all$estimate[2] < 0 & results_90_22_all$p.value[2] < 0.05,
"Yes", "No"),
ifelse(
results_90_22_oecd$estimate[2] < 0 & results_90_22_oecd$p.value[2] < 0.05,
"Yes", "No")
)
)
kable(summary_results,
caption = "Summary of Convergence Test Results",
col.names = c("Period", "Sample", "β (Convergence Parameter)",
"P-value", "R²", "Significant Convergence?"))
```
**Solow-Swan Prediction**:
- All countries should converge to the same income level due to diminishing returns to capital. Poor countries should grow faster than rich countries.
**Our Results**:
- The evidence for absolute convergence is mixed at best and depends heavily on the sample
- For a global sample, absolute convergence is not happening
- The group of OECD countries show stronger convergence patterns than the global sample, but only for the more recent time period the convergence parameter is significantly smaller than zero
- Even in this, the relationship is often weak (low R-squared values)
Why is it that absolute convergence is not happening as predicted by Solow-Swan?
The great thing about such models is that we can systematically think about which
of its assumptions might not hold:
1. **Different Technologies**: Countries may not have access to the same production technologies
2. **Institutional Differences**: Legal systems, property rights, and governance quality vary dramatically
3. **Human Capital**: Education and skill levels differ substantially across countries
4. **Savings Rates**: Cultural and policy differences affect investment rates
5. **Trade and Openness**: Some countries are more integrated into global markets
6. **Geography and Natural Resources**: Location and resource endowments matter
7. **Patterns of exploitation**: Maybe the success of some countries comes at the expense of other countires that would then not converge for obvious reasons.
The weak evidence for absolute convergence has led economists to focus on **conditional convergence** - the idea that countries converge to their own steady states, which may differ based on:
- Savings rates
- Population growth rates\
- Institutional quality
- Human capital levels
- Technology access
As you see, this addresses some of the possible explanations above.
Other economists, especially those working in Marxist and Dependency Theory traditions
would be even more skeptical, and argue for a systematic relationship between
development and underdevelopment, suggesting that studying conditional
convergence is not a fruitful endeavor either.
## Policy Implications
These findings have important implications for development policy:
1. **Investment Alone is Insufficient**: Simply increasing capital investment won't automatically generate catch-up growth
2. **Institutions Matter**: Countries need good governance, property rights, and effective institutions
3. **Human Capital is Crucial**: Education and skill development are essential for technology adoption
4. **Technology Transfer**: Facilitating technology transfer and innovation is key for developing countries
# Conclusion
Your empirical test of the Solow model's convergence prediction illustrates the complexity of real-world development. While you found some evidence of convergence among similar countries (like OECD members), the prediction of universal convergence does not hold for the global economy.
This doesn't mean the Solow model is wrong - rather, it highlights that the assumptions of identical technology, institutions, and preferences across countries are often violated in reality. The model remains valuable for understanding growth mechanics, but must be complemented with theories that account for institutional, technological, and structural differences between countries.
Understanding these limitations is crucial for development economists and policymakers who seek to design effective strategies for promoting economic growth and reducing global inequality.