For my first dataset, I selected life expectancy data from the World Bank. I explored how life expectancy changed across different countries before, during, and after the COVID-19 pandemic. My main goal was to understand whether countries recovered at the same rate or whether some continued to experience lower life expectancy.
The dataset comes from the World Bank’s World Development Indicators database.
The original dataset contains countries, regional aggregates, and separate columns for each year. I also used country metadata to identify regions and income groups.
How did life expectancy change between 2019 and 2024, and which countries experienced the strongest and weakest recoveries following the COVID-19 pandemic?
The original dataset was in wide format, with each year stored in a
separate column. I used pivot_longer() from the
tidyr package to convert the year columns into two
variables: Year and LifeExpectancy.
I also used dplyr to select the relevant columns, check
missing values, and remove regional aggregates using World Bank country
metadata. I kept the original CSV files unchanged and completed all
transformations in R.
I compared life expectancy in 2019, 2021, and 2024 to examine changes during and after the pandemic. I calculated the changes for individual countries and economies and compared patterns across income groups.
I also created line charts to show life expectancy trends and bar charts to highlight countries with the largest declines and strongest recoveries.
One challenge was separating individual countries and economies from regional aggregates. Some observations also had missing values or unusual year-to-year changes that required further attention.
Another important consideration was that changes in life expectancy could not automatically be attributed entirely to COVID-19, since other factors may have influenced the results.
The analysis included 217 countries and economies from the World Bank dataset. It identified countries with major life expectancy declines, countries with strong recoveries, and places that remained below their 2019 levels in 2024.
The project also demonstrated how data cleaning, reshaping, joining datasets, and visualization in R can help answer real-world research questions.
library(tidyverse)
library(knitr)
library(plotly)
library(countrycode)
life_raw <- read_csv(
"data/life_expectancy_wide.csv",
skip = 4,
show_col_types = FALSE
)
## New names:
## • `` -> `...71`
dim(life_raw)
## [1] 265 71
names(life_raw)
## [1] "Country Name" "Country Code" "Indicator Name" "Indicator Code"
## [5] "1960" "1961" "1962" "1963"
## [9] "1964" "1965" "1966" "1967"
## [13] "1968" "1969" "1970" "1971"
## [17] "1972" "1973" "1974" "1975"
## [21] "1976" "1977" "1978" "1979"
## [25] "1980" "1981" "1982" "1983"
## [29] "1984" "1985" "1986" "1987"
## [33] "1988" "1989" "1990" "1991"
## [37] "1992" "1993" "1994" "1995"
## [41] "1996" "1997" "1998" "1999"
## [45] "2000" "2001" "2002" "2003"
## [49] "2004" "2005" "2006" "2007"
## [53] "2008" "2009" "2010" "2011"
## [57] "2012" "2013" "2014" "2015"
## [61] "2016" "2017" "2018" "2019"
## [65] "2020" "2021" "2022" "2023"
## [69] "2024" "2025" "...71"
head(life_raw)
## # A tibble: 6 × 71
## `Country Name` `Country Code` `Indicator Name` `Indicator Code` `1960` `1961`
## <chr> <chr> <chr> <chr> <dbl> <dbl>
## 1 Aruba ABW Life expectancy… SP.DYN.LE00.IN 64.0 64.2
## 2 Africa Eastern… AFE Life expectancy… SP.DYN.LE00.IN 44.2 44.5
## 3 Afghanistan AFG Life expectancy… SP.DYN.LE00.IN 32.8 33.3
## 4 Africa Western… AFW Life expectancy… SP.DYN.LE00.IN 37.8 38.1
## 5 Angola AGO Life expectancy… SP.DYN.LE00.IN 37.9 36.9
## 6 Albania ALB Life expectancy… SP.DYN.LE00.IN 56.4 57.5
## # ℹ 65 more variables: `1962` <dbl>, `1963` <dbl>, `1964` <dbl>, `1965` <dbl>,
## # `1966` <dbl>, `1967` <dbl>, `1968` <dbl>, `1969` <dbl>, `1970` <dbl>,
## # `1971` <dbl>, `1972` <dbl>, `1973` <dbl>, `1974` <dbl>, `1975` <dbl>,
## # `1976` <dbl>, `1977` <dbl>, `1978` <dbl>, `1979` <dbl>, `1980` <dbl>,
## # `1981` <dbl>, `1982` <dbl>, `1983` <dbl>, `1984` <dbl>, `1985` <dbl>,
## # `1986` <dbl>, `1987` <dbl>, `1988` <dbl>, `1989` <dbl>, `1990` <dbl>,
## # `1991` <dbl>, `1992` <dbl>, `1993` <dbl>, `1994` <dbl>, `1995` <dbl>, …
The original World Bank dataset uses a wide format, where each row represents a country or regional aggregate and each year is stored in a separate column.
life_raw %>%
select(
`Country Name`,
`Country Code`,
`2019`:`2024`
) %>%
glimpse()
## Rows: 265
## Columns: 8
## $ `Country Name` <chr> "Aruba", "Africa Eastern and Southern", "Afghanistan", …
## $ `Country Code` <chr> "ABW", "AFE", "AFG", "AFW", "AGO", "ALB", "AND", "ARB",…
## $ `2019` <dbl> 76.01900, 63.85726, 62.94100, 57.14283, 63.05100, 79.46…
## $ `2020` <dbl> 75.40600, 63.76648, 61.45400, 57.35771, 63.11600, 77.82…
## $ `2021` <dbl> 73.65500, 62.98000, 60.41700, 57.35502, 62.95800, 76.84…
## $ `2022` <dbl> 76.22600, 64.48715, 65.61700, 57.97900, 64.24600, 78.76…
## $ `2023` <dbl> 76.35300, 65.14623, 66.03500, 58.84748, 64.61700, 79.60…
## $ `2024` <dbl> 76.50000, 65.34993, 66.28900, 59.04154, 64.80500, 79.77…
life_raw %>%
select(
`Country Name`,
`Country Code`,
`2019`,
`2020`,
`2021`,
`2022`,
`2023`,
`2024`
) %>%
head(10) %>%
kable(
caption = "Original Wide-Format Life Expectancy Data"
)
| Country Name | Country Code | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 |
|---|---|---|---|---|---|---|---|
| Aruba | ABW | 76.01900 | 75.40600 | 73.65500 | 76.22600 | 76.35300 | 76.50000 |
| Africa Eastern and Southern | AFE | 63.85726 | 63.76648 | 62.98000 | 64.48715 | 65.14623 | 65.34993 |
| Afghanistan | AFG | 62.94100 | 61.45400 | 60.41700 | 65.61700 | 66.03500 | 66.28900 |
| Africa Western and Central | AFW | 57.14283 | 57.35771 | 57.35502 | 57.97900 | 58.84748 | 59.04154 |
| Angola | AGO | 63.05100 | 63.11600 | 62.95800 | 64.24600 | 64.61700 | 64.80500 |
| Albania | ALB | 79.46700 | 77.82400 | 76.84400 | 78.76900 | 79.60200 | 79.77600 |
| Andorra | AND | 84.09800 | 79.41800 | 82.33100 | 84.01600 | 84.04100 | 84.18800 |
| Arab World | ARB | 71.83989 | 70.72656 | 70.40411 | 71.87610 | 72.44468 | 72.72181 |
| United Arab Emirates | ARE | 82.59600 | 81.93600 | 79.08300 | 80.48700 | 82.90900 | 83.06900 |
| Argentina | ARG | 76.84700 | 75.87800 | 73.94800 | 75.80600 | 77.39500 | 77.54300 |
The original World Bank dataset contained a separate column for each
year. I used pivot_longer() to transform these columns into
a single Year variable and a single
LifeExpectancy variable.
Since my research focused on changes between 2019 and 2024, I selected those years for the analysis.
life_tidy <- life_raw %>%
select(
`Country Name`,
`Country Code`,
`2019`:`2024`
) %>%
pivot_longer(
cols = `2019`:`2024`,
names_to = "Year",
values_to = "LifeExpectancy"
) %>%
mutate(
Year = as.integer(Year)
)
head(life_tidy, 12)
## # A tibble: 12 × 4
## `Country Name` `Country Code` Year LifeExpectancy
## <chr> <chr> <int> <dbl>
## 1 Aruba ABW 2019 76.0
## 2 Aruba ABW 2020 75.4
## 3 Aruba ABW 2021 73.7
## 4 Aruba ABW 2022 76.2
## 5 Aruba ABW 2023 76.4
## 6 Aruba ABW 2024 76.5
## 7 Africa Eastern and Southern AFE 2019 63.9
## 8 Africa Eastern and Southern AFE 2020 63.8
## 9 Africa Eastern and Southern AFE 2021 63.0
## 10 Africa Eastern and Southern AFE 2022 64.5
## 11 Africa Eastern and Southern AFE 2023 65.1
## 12 Africa Eastern and Southern AFE 2024 65.3
cat("Original dataset dimensions:\n")
## Original dataset dimensions:
dim(life_raw)
## [1] 265 71
cat("\nTidied dataset dimensions:\n")
##
## Tidied dataset dimensions:
dim(life_tidy)
## [1] 1590 4
cat("\nTidied dataset structure:\n")
##
## Tidied dataset structure:
glimpse(life_tidy)
## Rows: 1,590
## Columns: 4
## $ `Country Name` <chr> "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "Aruba", "…
## $ `Country Code` <chr> "ABW", "ABW", "ABW", "ABW", "ABW", "ABW", "AFE", "AFE",…
## $ Year <int> 2019, 2020, 2021, 2022, 2023, 2024, 2019, 2020, 2021, 2…
## $ LifeExpectancy <dbl> 76.01900, 75.40600, 73.65500, 76.22600, 76.35300, 76.50…
life_tidy %>%
head(12) %>%
kable(
digits = 2,
caption = "Life Expectancy Data After Tidying"
)
| Country Name | Country Code | Year | LifeExpectancy |
|---|---|---|---|
| Aruba | ABW | 2019 | 76.02 |
| Aruba | ABW | 2020 | 75.41 |
| Aruba | ABW | 2021 | 73.66 |
| Aruba | ABW | 2022 | 76.23 |
| Aruba | ABW | 2023 | 76.35 |
| Aruba | ABW | 2024 | 76.50 |
| Africa Eastern and Southern | AFE | 2019 | 63.86 |
| Africa Eastern and Southern | AFE | 2020 | 63.77 |
| Africa Eastern and Southern | AFE | 2021 | 62.98 |
| Africa Eastern and Southern | AFE | 2022 | 64.49 |
| Africa Eastern and Southern | AFE | 2023 | 65.15 |
| Africa Eastern and Southern | AFE | 2024 | 65.35 |
The World Bank dataset included both individual countries and regional aggregates. I used the country metadata file to identify countries and economies and add regional and income-group information.
country_metadata_raw <- read_csv(
"data/life_expectancy_countries.csv",
show_col_types = FALSE
)
## New names:
## • `` -> `...6`
dim(country_metadata_raw)
## [1] 264 6
names(country_metadata_raw)
## [1] "Country Code" "Region" "IncomeGroup" "SpecialNotes" "TableName"
## [6] "...6"
country_metadata_raw %>%
head(10) %>%
kable(caption = "World Bank Country Metadata")
| Country Code | Region | IncomeGroup | SpecialNotes | TableName | …6 |
|---|---|---|---|---|---|
| ABW | Latin America & Caribbean | High income | NA | Aruba | NA |
| AFE | NA | NA | 26 countries, stretching from the Red Sea in the North to the Cape of Good Hope in the South (https://www.worldbank.org/en/region/afr/eastern-and-southern-africa) | Africa Eastern and Southern | NA |
| AFG | Middle East & North Africa | Low income | The reporting period for national accounts data is designated as either calendar year basis (CY) or fiscal year basis (FY). For this country, it is fiscal year-based (fiscal year-end: March 20). Also, an estimate (PA.NUS.ATLS) of the exchange rate covers the same period and thus differs from the official exchange rate (CY). |
In addition, the World Bank systematically assesses the appropriateness of official exchange rates as conversion factors. In this country, multiple or dual exchange rate activity exists and must be accounted for appropriately in underlying statistics. An alternative estimate (“alternative conversion factor” - PA.NUS.ATLS) is thus calculated as a weighted average of the different exchange rates in use in the country. Doing so better reflects economic reality and leads to more accurate cross-country comparisons and country classifications by income level. For this country, this applies to the period 1960-2006. Alternative conversion factors are used in the Atlas methodology and elsewhere in World Development Indicators as single-year conversion factors. |Afghanistan |NA | |AFW |NA |NA |22 countries, stretching from the westernmost point of Africa, across the equator, and partly along the Atlantic Ocean till the Republic of Congo in the South (https://www.worldbank.org/en/region/afr/western-and-central-africa) |Africa Western and Central |NA | |AGO |Sub-Saharan Africa |Lower middle income |The World Bank systematically assesses the appropriateness of official exchange rates as conversion factors. In this country, multiple or dual exchange rate activity exists and must be accounted for appropriately in underlying statistics. An alternative estimate (“alternative conversion factor” - PA.NUS.ATLS) is thus calculated as a weighted average of the different exchange rates in use in the country. Doing so better reflects economic reality and leads to more accurate cross-country comparisons and country classifications by income level. For this country, this applies to the period 1994-2025. Alternative conversion factors are used in the Atlas methodology and elsewhere in World Development Indicators as single-year conversion factors. |Angola |NA | |ALB |Europe & Central Asia |Upper middle income |NA |Albania |NA | |AND |Europe & Central Asia |High income |NA |Andorra |NA | |ARB |NA |NA |Arab World aggregate. Arab World is composed of members of the League of Arab States. |Arab World |NA | |ARE |Middle East & North Africa |High income |NA |United Arab Emirates |NA | |ARG |Latin America & Caribbean |Upper middle income |Due to the limitations of the Atlas method in classifying countries experiencing persistent high inflation, this economy remains classified as upper-middle-income. The World Bank systematically assesses the appropriateness of official exchange rates as conversion factors. In this country, multiple or dual exchange rate activity exists and must be accounted for appropriately in underlying statistics. An alternative estimate (“alternative conversion factor” - PA.NUS.ATLS) is thus calculated as a weighted average of the different exchange rates in use in the country. Doing so better reflects economic reality and leads to more accurate cross-country comparisons and country classifications by income level. For this country, this applies to the period 1971-2018. Alternative conversion factors are used in the Atlas methodology and elsewhere in World Development Indicators as single-year conversion factors. |Argentina |NA |
glimpse(country_metadata_raw)
## Rows: 264
## Columns: 6
## $ `Country Code` <chr> "ABW", "AFE", "AFG", "AFW", "AGO", "ALB", "AND", "ARB",…
## $ Region <chr> "Latin America & Caribbean", NA, "Middle East & North A…
## $ IncomeGroup <chr> "High income", NA, "Low income", NA, "Lower middle inco…
## $ SpecialNotes <chr> NA, "26 countries, stretching from the Red Sea in the N…
## $ TableName <chr> "Aruba", "Africa Eastern and Southern", "Afghanistan", …
## $ ...6 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
I joined the tidied life expectancy dataset with the World Bank
country metadata using Country Code.
I then removed regional aggregates by keeping records with valid region and income-group classifications.
country_metadata <- country_metadata_raw %>%
select(
`Country Code`,
Region,
IncomeGroup
) %>%
distinct(`Country Code`, .keep_all = TRUE)
country_metadata %>%
head(10) %>%
kable(caption = "Cleaned Country Metadata")
| Country Code | Region | IncomeGroup |
|---|---|---|
| ABW | Latin America & Caribbean | High income |
| AFE | NA | NA |
| AFG | Middle East & North Africa | Low income |
| AFW | NA | NA |
| AGO | Sub-Saharan Africa | Lower middle income |
| ALB | Europe & Central Asia | Upper middle income |
| AND | Europe & Central Asia | High income |
| ARB | NA | NA |
| ARE | Middle East & North Africa | High income |
| ARG | Latin America & Caribbean | Upper middle income |
life_joined <- life_tidy %>%
left_join(
country_metadata,
by = "Country Code"
)
cat("Rows after joining:", nrow(life_joined), "\n")
## Rows after joining: 1590
life_joined %>%
head(10) %>%
kable(
digits = 2,
caption = "Life Expectancy Data with Country Metadata"
)
| Country Name | Country Code | Year | LifeExpectancy | Region | IncomeGroup |
|---|---|---|---|---|---|
| Aruba | ABW | 2019 | 76.02 | Latin America & Caribbean | High income |
| Aruba | ABW | 2020 | 75.41 | Latin America & Caribbean | High income |
| Aruba | ABW | 2021 | 73.66 | Latin America & Caribbean | High income |
| Aruba | ABW | 2022 | 76.23 | Latin America & Caribbean | High income |
| Aruba | ABW | 2023 | 76.35 | Latin America & Caribbean | High income |
| Aruba | ABW | 2024 | 76.50 | Latin America & Caribbean | High income |
| Africa Eastern and Southern | AFE | 2019 | 63.86 | NA | NA |
| Africa Eastern and Southern | AFE | 2020 | 63.77 | NA | NA |
| Africa Eastern and Southern | AFE | 2021 | 62.98 | NA | NA |
| Africa Eastern and Southern | AFE | 2022 | 64.49 | NA | NA |
life_clean <- life_joined %>%
filter(
!is.na(Region),
!is.na(IncomeGroup)
)
cat("Rows before filtering:", nrow(life_joined), "\n")
## Rows before filtering: 1590
cat("Rows after filtering:", nrow(life_clean), "\n")
## Rows after filtering: 1302
cat(
"Number of countries:",
n_distinct(life_clean$`Country Code`),
"\n"
)
## Number of countries: 217
life_clean %>%
head(10) %>%
kable(
digits = 2,
caption = "Cleaned Country-Level Life Expectancy Data"
)
| Country Name | Country Code | Year | LifeExpectancy | Region | IncomeGroup |
|---|---|---|---|---|---|
| Aruba | ABW | 2019 | 76.02 | Latin America & Caribbean | High income |
| Aruba | ABW | 2020 | 75.41 | Latin America & Caribbean | High income |
| Aruba | ABW | 2021 | 73.66 | Latin America & Caribbean | High income |
| Aruba | ABW | 2022 | 76.23 | Latin America & Caribbean | High income |
| Aruba | ABW | 2023 | 76.35 | Latin America & Caribbean | High income |
| Aruba | ABW | 2024 | 76.50 | Latin America & Caribbean | High income |
| Afghanistan | AFG | 2019 | 62.94 | Middle East & North Africa | Low income |
| Afghanistan | AFG | 2020 | 61.45 | Middle East & North Africa | Low income |
| Afghanistan | AFG | 2021 | 60.42 | Middle East & North Africa | Low income |
| Afghanistan | AFG | 2022 | 65.62 | Middle East & North Africa | Low income |
missing_summary <- life_clean %>%
group_by(Year) %>%
summarise(
TotalRecords = n(),
MissingLifeExpectancy = sum(is.na(LifeExpectancy)),
AvailableLifeExpectancy = sum(!is.na(LifeExpectancy)),
.groups = "drop"
)
missing_summary %>%
kable(
caption = "Missing Life Expectancy Values by Year"
)
| Year | TotalRecords | MissingLifeExpectancy | AvailableLifeExpectancy |
|---|---|---|---|
| 2019 | 217 | 0 | 217 |
| 2020 | 217 | 0 | 217 |
| 2021 | 217 | 0 | 217 |
| 2022 | 217 | 0 | 217 |
| 2023 | 217 | 0 | 217 |
| 2024 | 217 | 0 | 217 |
To understand how life expectancy changed during and after the COVID-19 pandemic, I compared life expectancy in 2019, 2021, and 2024.
The analysis measured changes during the pandemic period, recovery after 2021, and the overall difference from the pre-pandemic baseline.
life_changes <- life_clean %>%
filter(Year %in% c(2019, 2021, 2024)) %>%
select(
`Country Name`,
`Country Code`,
Region,
IncomeGroup,
Year,
LifeExpectancy
) %>%
pivot_wider(
names_from = Year,
values_from = LifeExpectancy,
names_prefix = "Life_"
) %>%
mutate(
PandemicChange = Life_2021 - Life_2019,
RecoveryChange = Life_2024 - Life_2021,
OverallChange = Life_2024 - Life_2019
)
life_changes %>%
head(10) %>%
kable(
digits = 2,
caption = "Life Expectancy Changes by Country"
)
| Country Name | Country Code | Region | IncomeGroup | Life_2019 | Life_2021 | Life_2024 | PandemicChange | RecoveryChange | OverallChange |
|---|---|---|---|---|---|---|---|---|---|
| Aruba | ABW | Latin America & Caribbean | High income | 76.02 | 73.66 | 76.50 | -2.36 | 2.84 | 0.48 |
| Afghanistan | AFG | Middle East & North Africa | Low income | 62.94 | 60.42 | 66.29 | -2.52 | 5.87 | 3.35 |
| Angola | AGO | Sub-Saharan Africa | Lower middle income | 63.05 | 62.96 | 64.81 | -0.09 | 1.85 | 1.75 |
| Albania | ALB | Europe & Central Asia | Upper middle income | 79.47 | 76.84 | 79.78 | -2.62 | 2.93 | 0.31 |
| Andorra | AND | Europe & Central Asia | High income | 84.10 | 82.33 | 84.19 | -1.77 | 1.86 | 0.09 |
| United Arab Emirates | ARE | Middle East & North Africa | High income | 82.60 | 79.08 | 83.07 | -3.51 | 3.99 | 0.47 |
| Argentina | ARG | Latin America & Caribbean | Upper middle income | 76.85 | 73.95 | 77.54 | -2.90 | 3.60 | 0.70 |
| Armenia | ARM | Europe & Central Asia | Upper middle income | 76.22 | 72.28 | 78.32 | -3.94 | 6.04 | 2.10 |
| American Samoa | ASM | East Asia & Pacific | High income | 72.75 | 72.71 | 72.99 | -0.04 | 0.28 | 0.24 |
| Antigua and Barbuda | ATG | Latin America & Caribbean | High income | 77.17 | 77.20 | 77.77 | 0.03 | 0.57 | 0.60 |
life_changes %>%
summarise(
TotalCountries = n(),
CompleteComparisons = sum(
!is.na(Life_2019) &
!is.na(Life_2021) &
!is.na(Life_2024)
),
MissingComparisons = sum(
is.na(Life_2019) |
is.na(Life_2021) |
is.na(Life_2024)
)
) %>%
kable(
caption = "Data Availability for Country Comparisons"
)
| TotalCountries | CompleteComparisons | MissingComparisons |
|---|---|---|
| 217 | 217 | 0 |
life_changes %>%
filter(!is.na(PandemicChange)) %>%
arrange(PandemicChange) %>%
select(
`Country Name`,
Region,
PandemicChange
) %>%
head(10) %>%
kable(
digits = 2,
caption = "10 Largest Life Expectancy Declines, 2019–2021"
)
| Country Name | Region | PandemicChange |
|---|---|---|
| Bolivia | Latin America & Caribbean | -6.39 |
| Paraguay | Latin America & Caribbean | -5.56 |
| Mexico | Latin America & Caribbean | -4.78 |
| Guyana | Latin America & Caribbean | -4.74 |
| Peru | Latin America & Caribbean | -4.68 |
| Lebanon | Middle East & North Africa | -4.56 |
| Ecuador | Latin America & Caribbean | -4.54 |
| Cuba | Latin America & Caribbean | -4.21 |
| Colombia | Latin America & Caribbean | -4.10 |
| South Africa | Sub-Saharan Africa | -4.06 |
life_changes %>%
filter(!is.na(RecoveryChange)) %>%
arrange(desc(RecoveryChange)) %>%
select(
`Country Name`,
Region,
RecoveryChange
) %>%
head(10) %>%
kable(
digits = 2,
caption = "10 Largest Life Expectancy Increases, 2021–2024"
)
| Country Name | Region | RecoveryChange |
|---|---|---|
| Central African Republic | Sub-Saharan Africa | 17.39 |
| Bolivia | Latin America & Caribbean | 7.31 |
| Namibia | Sub-Saharan Africa | 6.67 |
| Peru | Latin America & Caribbean | 6.34 |
| Armenia | Europe & Central Asia | 6.04 |
| Eswatini | Sub-Saharan Africa | 6.04 |
| Guyana | Latin America & Caribbean | 6.00 |
| Botswana | Sub-Saharan Africa | 5.99 |
| Paraguay | Latin America & Caribbean | 5.87 |
| Afghanistan | Middle East & North Africa | 5.87 |
life_changes %>%
filter(!is.na(OverallChange), OverallChange < 0) %>%
arrange(OverallChange) %>%
select(
`Country Name`,
Region,
OverallChange
) %>%
head(10) %>%
kable(
digits = 2,
caption = "Countries Furthest Below 2019 Life Expectancy in 2024"
)
| Country Name | Region | OverallChange |
|---|---|---|
| West Bank and Gaza | Middle East & North Africa | -6.60 |
| Libya | Middle East & North Africa | -1.82 |
| Greenland | Europe & Central Asia | -1.14 |
| Thailand | East Asia & Pacific | -0.63 |
| Macao SAR, China | East Asia & Pacific | -0.60 |
| Germany | Europe & Central Asia | -0.50 |
| Mauritius | Sub-Saharan Africa | -0.45 |
| Qatar | Middle East & North Africa | -0.42 |
| South Sudan | Sub-Saharan Africa | -0.39 |
| Iceland | Europe & Central Asia | -0.35 |
income_trends <- life_clean %>%
group_by(IncomeGroup, Year) %>%
summarise(
AverageLifeExpectancy = mean(
LifeExpectancy,
na.rm = TRUE
),
.groups = "drop"
)
ggplot(
income_trends,
aes(
x = Year,
y = AverageLifeExpectancy,
color = IncomeGroup,
group = IncomeGroup
)
) +
geom_line(linewidth = 1.2) +
geom_point(size = 2.5) +
scale_x_continuous(breaks = 2019:2024) +
labs(
title = "Life Expectancy Trends by Income Group",
subtitle = "Average country-level life expectancy, 2019–2024",
x = "Year",
y = "Life Expectancy (Years)",
color = "Income Group",
caption = "Source: World Bank World Development Indicators"
) +
theme_minimal()
This visualization compares average life expectancy across different income groups from 2019 to 2024. It helps show how life expectancy changed during and after the COVID-19 pandemic and whether recovery patterns differed between income groups. The chart also highlights the differences in life expectancy levels across these groups. Each average represents the countries and economies with available data, rather than a population-weighted global average.
largest_declines <- life_changes %>%
filter(!is.na(PandemicChange)) %>%
slice_min(
PandemicChange,
n = 10,
with_ties = FALSE
)
ggplot(
largest_declines,
aes(
x = reorder(`Country Name`, PandemicChange),
y = PandemicChange
)
) +
geom_col(fill = "#C44E52") +
coord_flip() +
labs(
title = "Countries with the Largest Life Expectancy Declines",
subtitle = "Change from 2019 to 2021",
x = "Country",
y = "Change in Life Expectancy (Years)",
caption = "Source: World Bank World Development Indicators"
) +
theme_minimal()
This visualization shows the 10 countries with the largest life expectancy declines between 2019 and 2021. Bolivia experienced the largest decline at approximately 6.39 years, followed by Paraguay at 5.56 years and Mexico at 4.78 years. Several Latin American countries appear in this chart, showing how strongly life expectancy was affected in parts of the region during the pandemic period.
strongest_recoveries <- life_changes %>%
filter(!is.na(RecoveryChange)) %>%
slice_max(
RecoveryChange,
n = 10,
with_ties = FALSE
)
ggplot(
strongest_recoveries,
aes(
x = reorder(`Country Name`, RecoveryChange),
y = RecoveryChange
)
) +
geom_col(fill = "#4C9F70") +
coord_flip() +
labs(
title = "Countries with the Strongest Life Expectancy Recoveries",
subtitle = "Change from 2021 to 2024",
x = "Country",
y = "Increase in Life Expectancy (Years)",
caption = "Source: World Bank World Development Indicators"
) +
theme_minimal()
This visualization shows the countries with the largest increases in life expectancy between 2021 and 2024. The Central African Republic had the largest reported increase at 17.4 years, but its data contain unusual fluctuations that require verification. Bolivia followed with an increase of 7.31 years, Namibia with 6.67 years, and Peru with 6.34 years. The results show that countries recovered at different rates, and a strong recovery did not always mean returning to pre-pandemic levels.
The Central African Republic has unusually large changes in life expectancy between consecutive years. I reviewed these observations separately because they may influence the ranking of countries with the strongest recoveries.
life_clean %>%
filter(`Country Code` == "CAF") %>%
arrange(Year) %>%
select(Year, LifeExpectancy) %>%
kable(
digits = 2,
caption = "Central African Republic Life Expectancy, 2019–2024"
)
| Year | LifeExpectancy |
|---|---|
| 2019 | 31.53 |
| 2020 | 50.60 |
| 2021 | 40.28 |
| 2022 | 18.82 |
| 2023 | 57.41 |
| 2024 | 57.67 |
These unusually large changes, especially the decrease in 2022 followed by a sharp increase in 2023, suggest that this country’s results should be interpreted cautiously until the source data can be verified.
This interactive map shows how life expectancy changed across countries between 2019 and 2024 compared with their 2019 levels. Use the year slider to explore changes over time.
map_data <- life_clean %>%
group_by(`Country Code`) %>%
mutate(
Life2019 = LifeExpectancy[match(2019, Year)],
ChangeFrom2019 = LifeExpectancy - Life2019
) %>%
ungroup() %>%
filter(
!is.na(ChangeFrom2019),
!is.na(LifeExpectancy)
) %>%
mutate(
HoverText = paste0(
"<b>", `Country Name`, "</b>",
"<br>Year: ", Year,
"<br>Life Expectancy: ",
round(LifeExpectancy, 2), " years",
"<br>Change from 2019: ",
sprintf("%+.2f", ChangeFrom2019), " years"
)
)
plot_ly(
data = map_data,
type = "choropleth",
locations = ~`Country Code`,
locationmode = "ISO-3",
z = ~ChangeFrom2019,
frame = ~Year,
text = ~HoverText,
hoverinfo = "text",
colorscale = list(
c(0, "#C44E52"),
c(0.5, "#F7F7F7"),
c(1, "#4C9F70")
),
zmin = -10,
zmax = 10,
zmid = 0,
colorbar = list(title = "Change (Years)")
) %>%
layout(
title = "Global Life Expectancy Change Since 2019",
geo = list(
showframe = FALSE,
showcoastlines = TRUE,
projection = list(type = "natural earth")
)
) %>%
animation_opts(
frame = 1000,
transition = 500,
redraw = TRUE
) %>%
animation_slider(
currentvalue = list(prefix = "Year: ")
)
The interactive map uses red to represent countries with lower life expectancy than in 2019 and green for countries with higher life expectancy. Viewers can move the year slider to compare different years and hover over countries to see their values. Countries without available data or a matching map location may not be colored.
Although many countries experienced increases in life expectancy after 2021, some had not returned to their 2019 levels by 2024. West Bank and Gaza showed the largest overall decline at approximately 6.60 years, followed by Libya and Greenland. This shows that recovery was not equal across countries.
Some countries have missing data or unusual changes that require verification. The dataset also includes territories and economies, not just independent countries. Additionally, changes in life expectancy cannot be attributed entirely to COVID-19 because other factors may have influenced the results. Countries with missing life expectancy values were excluded from comparisons requiring those years, so the rankings only include countries with available data.
This project analyzed life expectancy across 217 countries and economies from 2019 to 2024 using World Bank data. The results show that many countries experienced declines during the pandemic period and recovered afterward, but not at the same rate. By cleaning, transforming, and visualizing the data in R, I was able to identify differences in life expectancy recovery across countries and income groups.