Was Brazil’s performance in poverty alleviation an extraordinary one under Lula’s and Dilma Rouseff’s administrations? Looking into data from the World Bank’s API with Python.
Dr. rer. pol. Eduardo W. Ferreira (Ph. D.)
The arrest of former Brazil’s President Luiz Inacio Lula da Silva due to corruption and money laundering crimes have disappointed many of his supporters. This and other arrests of prominent politicians and business leaders have renewed hopes that rule of law was gradually starting to apply to the powerful.
Lula still remains a wildly popular leader whose administrations were credited with bringing millions out of poverty in one of the world’s most unequal countries1. Some of Lula’s supporters have insistently argued that without his government administrations (and “almost” two other ones of his successor), poverty alleviation would not have taken place. They often portrait Brazil’s performance in this regards as something unique in the world and dependent mainly on Lula. Following this argument, many supporters have claimed political persecution of Lula by elites that now could not bear travelling in airplanes together with the poor who thanks to Lula became able to afford it. Such strong assumptions seem exaggerated.
Matt Ridley’s best seller The Evolution of Everything: How New Ideas Emerge, for example, explains very nicely that:
Change in technology, language, morality, and society is incremental, inexorable, gradual, and spontaneous. It follows a narrative, going from one stage to the next, and it largely happens by trial and error – a version of natural selection. Much of the human world is the result of human action but not of human design: it emerges from the interactions of millions, not from the plans of a few.
So, I thought that a fresh look into the newest poverty indicators could help avoiding people falling into exaggerated claims by politicians in Brazil and in other countries.
Although there are many analyses indicating that poverty reduction has been a global phenomenum, I wanted to investigate this myself directly from World Bank’s datasets using Python. The examined indicator was the poverty headcount ratio at $1.90 a day (2011 PPP) (% of population) from 2000 to 2016. This is the share of the population living in the bottom of the pyramid.
For that, I employed a range of libraries including Wbdata. This is a great python interface to find and request information from the World Bank’s various databases, either as a dictionary containing full metadata or as a pandas DataFrame. Currently, wbdata wraps most of the World Bank API, and also adds some convenience functions for searching and retrieving information.
The code chunks and output below present all the steps for downloading, cleaning and visualising data. Hash signs (“#”) indicate my explanatory comments to allow full auditing of results and reproducibility.
The plot above and results below do not suggest that the reduction in terms of poverty headcount ratio at $1.90 a day (2011 PPP) (% of population) was a particularly astonishing one in Brazil. Most importantly, this was a global phenomenum. It would be very surprising if Brazil had not reduced the share of its population living under extreme poverty. Hence, the argument that the verified poverty alleviation is something unique of Brazil and that it should be a reason for pardoning crimes of corrupt politicians seems to be a weak one. However, it can be useful in an election year as 2018 in an unequal and politically polarised country such as Brazil.
For transparency and reproducibility, all the steps taken to generate the plot using Python 3.6.4 are presented below. Suggestions for improvement are always welcome! Have fun, keep coding and vote wisely.
# Imports required libs
import pandas as pd
from pandas.io.json import json_normalize
from datetime import datetime
from pandas import Series, DataFrame
import numpy as np
import matplotlib.pyplot as plt
# Reads data as JSON
## Poverty headcount ratio at $1.90 a day (2011 PPP) (% of population)
SIPOVDDAY = wbdata.get_data(“SI.POV.DDAY”)
# Converts data as dataframe
# Selects columns of interest
povdata = df[[“date”, “country.value”, “value”]]
# Converts years to integer numebrs and subsets data as from 2000
povdata = povdata[povdata[“date”].astype(np.int)>=2000]
# Change variable type to float
povdata[“value”] = povdata[“value”].astype(np.float)
povdata.columns = [u’date’, u’country’, u’value’]
# Drops regional data
povdata = povdata[~povdata[‘country’].isin([“Arab World”, “Caribbean small states”, “Central Europe and the Baltics”,
“Early-demographic dividend”, “East Asia & Pacific”,
“East Asia & Pacific (excluding high income)”,
“East Asia & Pacific (IDA & IBRD countries)”, “Euro area”,
“Europe & Central Asia”, “Europe & Central Asia (excluding high income)”,
“Europe & Central Asia (IDA & IBRD countries)”, “European Union”,
“Fragile and conflict affected situations”,
“Heavily indebted poor countries (HIPC)”, “High income”, “IBRD only”,
“IDA & IBRD total”, “IDA blend”, “IDA only”, “IDA total”, “Late-demographic dividend”,
“Latin America & Caribbean”, “Latin America & Caribbean (excluding high income)”,
“Latin America & the Caribbean (IDA & IBRD countries)”,
“Least developed countries: UN classification”,
“Low & middle income”, “Low income”, “Lower middle income”,
“Middle income”, “High income”, “Middle East & North Africa”,
“Middle East & North Africa (excluding high income)”,
“Middle East & North Africa (IDA & IBRD countries)”, “North America”,
“Not classified”, “OECD members”, “Other small states”,
“Pacific island small states”, “Post-demographic dividend”,
“Pre-demographic dividend”, “Small states”, “South Asia”,
“South Asia (excluding high income)”,
“South Asia (IDA & IBRD)”, “Sub-Saharan Africa”,
“Sub-Saharan Africa (excluding high income)”,
“Sub-Saharan Africa (IDA & IBRD countries)”, “Upper middle income”, “World”
The dataset spans a period of 18 years with data for 217 countries as presented in the summary table below (see row “unique” for column “country”). Not all countries have data for all years (see pivot table in the end of this notebook).
# Describes clean dataset
# Filters dates after 2000 and drops NaNs (missing data)
povdata = povdata[povdata[“date”].astype(np.int)>=2000].dropna()
The table below describes the dataset once we have removed missing data and subset only countries with at least 10 years of data as from 2000. From the 217 countries, only 51 remain in the dataset. Brazil has 14 years of data available for the indicator of interest / Poverty headcount ratio at $1.90 a day (2011 PPP) (% of population).
# Drops NAs for values and counts remaining observations by country
subsetpovdata = povdata.dropna(subset=[‘value’]).groupby(‘country’).count()
# Subsets only those countries with at least 10 years of data
subsetpovdata = subsetpovdata.loc[subsetpovdata[“value”]>10]
# Filters dataset based on subset
povdata = povdata.loc[povdata[“country”].isin(subsetpovdata.index)]
# Prints shape of dataset
The table below provides summary statistics for Brazil’s poverty headcount ratio at $1.90 a day (2011 PPP) (% of population).
# Subsets data for Brazil only
povdatabr = povdata[povdata[“country”]==”Brazil”].sort_values(by=[‘date’])
# Implements linear interpolation to fill in missing data
povdatabr = povdatabr.interpolate(method=’linear’, axis=0).ffill().bfill()
# Describes data for Brazil
This is the ultimate plot that I was looking for. Brazil indeed experienced a reduction in the poverty headcount ratio at $1.90 a day (2011 PPP) (% of population). It started from a better point than many countries but the slope of the line does not seem extraordinary when compared to other countries.
# Creates empty plot
fig = plt.figure(); ax = fig.add_subplot(1,1,1)
labels = ax.set_xticklabels(povdata.pivot(“country”, “date”, “value”).columns,
fontsize = “small”, rotation = 45)
# Plots values for all countries with available data for the period
ax.plot(povdata[“date”], povdata[“value”], “k–“,
label = “Other countries”, color = “y”, alpha=0.7)
# Plots values for Brazil
ax.plot(povdatabr[“date”], povdatabr[“value”], “k”,
label = “Brazil”, color = “green”, marker = “o”)
# Includes title, legend and labels
ax.set_title(“Poverty headcount ratio at $1.90 a day (2011 PPP) (% of population)”)
ax.legend(loc = “best”, frameon = False)
ax.set_ylabel(“% of population”)
# Draws vertical line and annotation indicating start of Lula’s presidency
plt.plot([2003, 2003], [0, 11.1], ‘k–‘, lw=1)
ax.annotate(‘Start of Lula\’s presidency’, xy=(2003, 35), xytext=(2003, 35),
rotation = 90, fontsize = “small”, alpha = 0.7)
# Draws vertical line indicating end of Lula’s presidency and start of Dilma’s
plt.plot([2011, 2011], [0, 4.7], ‘k–‘, lw=1)
ax.annotate(‘Lula\’s succession by Rouseff’, xy=(2011, 31), xytext=(2011, 31),
rotation = 90, fontsize = “small”, alpha = 0.7)
# Draws vertical line indicating end of Dilma’s presidency
plt.plot([2016, 2016], [0, 3.4], ‘k–‘, lw=1)
ax.annotate(‘End of Rouseff\’s presidency’, xy=(2016, 29), xytext=(2016, 29),
rotation = 90, fontsize = “small”, alpha = 0.7)
The pivot table below presents the original values behind this one plot above. Missing data for Brazil has been filled in by linear interpolation in the plot above. That is the reason why the series for Brazil in the plot above also contains data for 2000, 2010, 2016 and 2017 although in the table below it appears as missing data (NaN).
# Pivots data
povdatapivot = povdata.pivot(“country”, “date”, “value”)
# Prints pivot data
- SAVARESE, M. & PRENGAMAN, P. (2018) “Brazil Is Bracing for the Arrest of Former President Luiz Inacio Lula da Silva”, Times Magazine, 6 April 2018. Available at: https://time.com/5230915/brazil-former-president-lula-da-silva-arrest-warrant/ ↩