In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

Wealth Distribution

One way that we might understand equality is through understanding the distribution of wealth in a society. Perfect wealth distribution would mean that all participants have the same share of wealth as everyone else. We can represent this situation mathematically with a function \(L(x) = x\) that we will call the Lorenz Curve.

Concretely, if we were to look at every 20% of the population, we would see 20% of income.

Fifths of Households Percent of Wealth
Lowest Fifth 20
Lowest two - Fifths 40
Lowest three - Fifths 60
Lowest four - Fifths 80
Lowest five - Fifths 100
In [2]:
percent = [0, 0.2, 0.4, 0.6, 0.8, 1.0]
lorenz = [0, 0.2, 0.4, 0.6, 0.8, 1.0]
In [3]:
plt.plot(percent, lorenz, '-o')
plt.title("Perfect Wealth Distribution")
Out[3]:
<matplotlib.text.Text at 0x118c4c7f0>
_images/0.11_calc_Gini_Index_4_1.png

It is unlikely that we have perfect distribution of wealth in a society however. For example, the following table describes the cumulative distribution of income in the United States for the year 1994.

Fifths of Households Percent of Wealth
Lowest Fifth 4.2
Lowest two - Fifths 14.2
Lowest three - Fifths 29.9
Lowest four - Fifths 53.2
Lowest five - Fifths 100.0
In [4]:
usa_94 = [0, 0.042, 0.142, 0.299, 0.532, 1.00]
In [5]:
plt.figure(figsize = (9, 5))
plt.plot(percent, lorenz, '-o', label = 'Lorenz Curve')
plt.plot(percent, usa_94, '-o', label = 'USA 1994')
plt.title("The Difference between Perfect and Actual Wealth Equality")
plt.legend(loc = 'best', frameon = False)
Out[5]:
<matplotlib.legend.Legend at 0x119289c50>
_images/0.11_calc_Gini_Index_7_1.png

The area between these curves can be understood to represent the discrepency between perfect wealth distribution and levels of inequality. Further, if we examine the ratio between this area and that under the Lorenz Curve we get the Gini Index.

One big issue remains however. We don’t want to use rectangles to approximate these regions but we don’t have equations for the actual distribution of wealth. We introduce two curve fitting techniques using numpy to address this problem.

Quadratic Fit

The curve in the figure above representing the actual distribution of wealth in the USA in 1994 can be approximated by a polynomial function. NumPy has a function called polyfit that will fit a polynomial to a set of points. Here, we use polyfit to fit a quadratic function to the points.

In [6]:
fit = np.poly1d(np.polyfit(percent, usa_94, 2))
In [7]:
plt.figure(figsize = (9, 5))
plt.plot(percent, usa_94, '-o', label = 'Polyfit')
plt.plot(percent, fit(percent), '-o', label = 'Actual USA 1994')
plt.title("Quality of Quadratic Fit")
plt.legend(loc = 'best', frameon = False)
Out[7]:
<matplotlib.legend.Legend at 0x119619f98>
_images/0.11_calc_Gini_Index_11_1.png

Getting the Fit

Below, we return to the complete picture where we plot our fitted function and the Lorenz Curve and shade the area that represents the difference in income distribution.

In [8]:
plt.figure(figsize = (9, 5))
plt.plot(percent, lorenz, '--o', label = 'Lorenz')
plt.plot(percent, fit(percent), '--o', label = 'Polyfit')
plt.fill_between(percent, lorenz, fit(percent), alpha = 0.3, color = 'burlywood')
plt.title("Visualizing the Gini Index")
plt.legend(loc = 'best', frameon = False)
Out[8]:
<matplotlib.legend.Legend at 0x1197d9c50>
_images/0.11_calc_Gini_Index_13_1.png

Now, we want to compute the ratio between the area between the curves to that under the Lorenz Curve. We can do this easily in Sympy but declaring \(x\) a symbol and substituting it into our fit function then integrating this.

In [9]:
import sympy as sy
In [10]:
x = sy.Symbol('x')
fit(x)
Out[10]:
x*(1.18839285714286*x - 0.241678571428574) + 0.0209285714285723
In [11]:
A_btwn = sy.integrate((x - fit(x)), (x, 0, 1))
In [12]:
A_L = sy.integrate(x, (x, 0,1))
In [13]:
A_btwn/A_L
Out[13]:
0.407559523809523

Inequality through Time

Now that we understand how to compute the Gini Index, we want to explore what improving the gap in wealth distribution would mean.

In [14]:
x = np.linspace(0, 1, 100)
plt.figure(figsize = (10, 7))
plt.plot(x, x)
plt.plot(x, x**2, label = "Country A")
plt.plot(x, x**4, label = "Country B")
plt.plot(x, x**8, label = "Country C")
plt.plot(x, x**16, label = "Country D")
plt.ylabel("Income Percent")
plt.xlabel("Population Fraction")
plt.title("Different Wealth Distributions")
plt.legend(loc = "best", frameon = False)
Out[14]:
<matplotlib.legend.Legend at 0x11aa4e860>
_images/0.11_calc_Gini_Index_21_1.png

Which of the above countries do you believe is the most equitable? Why?

Census Bureau Data and Pandas

There are many organizations that use the Gini Index to this day. The OECD, World Bank, and US Census all track Gini Indicies. We want to investigate the real data much as we have with our smaller examples. To do so, we will use the Pandas library.

The table below gives distribution data for the years 1970, 1980, 1990, and 2000.

x 0.0 0.2 0.4 0.6 0.8 1.0
1970 0.000 0.041 0.149 0.323 0.568 1.000
1980 0.000 0.042 0.144 0.312 0.559 1.000
1990 0.000 0.038 0.134 0.293 0.530 1.000
2000 0.000 0.036 0.125 0.273 0.503 1.000

Creating the DataFrame

We will begin by creating a table from this data by entering lists with these values and creating a DataFrame from these lists.

In [15]:
import pandas as pd
seventies = [0, 0.041, 0.149, 0.323, 0.568, 1.0]
eighties = [0, 0.042, 0.144, 0.312, 0.559, 1.0]
nineties = [0, 0.038, 0.134, 0.293, 0.53, 1.0]
twothou = [0, 0.036, 0.125, 0.273, 0.503, 1.0]
In [16]:
df = pd.DataFrame({'1970s': seventies, '1980s':eighties, '1990s': nineties,
                  '2000s': twothou, 'perfect': [0, 0.2, 0.4, 0.6, 0.8, 1.0]})
df.head()
Out[16]:
1970s 1980s 1990s 2000s perfect
0 0.000 0.000 0.000 0.000 0.0
1 0.041 0.042 0.038 0.036 0.2
2 0.149 0.144 0.134 0.125 0.4
3 0.323 0.312 0.293 0.273 0.6
4 0.568 0.559 0.530 0.503 0.8

Plotting from the DataFrame

We can plot directly from the dataframe. The default plot generates lines for each decades inequality distribution. There are many plot types available however, and we can specify them with the kind argument as demonstrated with the density plot that follows. What do these visualizations tell you about equality in the USA based on this data?

In [17]:
df.plot(figsize = (10, 8))
Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0x122d7a518>
_images/0.11_calc_Gini_Index_27_1.png
In [18]:
df.plot(kind = 'kde')
Out[18]:
<matplotlib.axes._subplots.AxesSubplot at 0x11a9efc88>
_images/0.11_calc_Gini_Index_28_1.png