Created
March 11, 2018 18:48
-
-
Save robert/7eee027244f81523e57b1f3df32cb6a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import random | |
import plotly | |
import plotly.graph_objs as go | |
N_QUINTILES = 5 | |
def gini(array): | |
"""Calculate the Gini coefficient of a numpy array. | |
Copied from https://github.com/oliviaguest/gini . | |
""" | |
array = np.asarray(array) | |
# based on bottom eq: | |
# http://www.statsdirect.com/help/generatedimages/equations/equation154.svg | |
# from: | |
# http://www.statsdirect.com/help/default.htm#nonparametric_methods/gini.htm | |
# All values are treated equally, arrays must be 1d: | |
array = array.flatten() | |
array = np.sort(array) | |
index = np.arange(1,array.shape[0]+1) | |
n = array.shape[0] | |
return ((np.sum((2 * index - n - 1) * array)) / float(n * np.sum(array))) | |
def transfer(orig_data, gini_diff, from_quintile, to_quintiles): | |
total_wealth = np.sum(orig_data) | |
gini_diff_per_amount_transfered = 0 | |
for to_q in to_quintiles: | |
transfer_distance = float(abs(to_q - from_quintile)) / N_QUINTILES | |
gini_diff_per_amount_transfered += transfer_distance * 2 / float(total_wealth) | |
amount_to_transfer = gini_diff / gini_diff_per_amount_transfered | |
new_data = np.copy(orig_data) | |
for to_q in to_quintiles: | |
new_data[to_q] = new_data[to_q] + amount_to_transfer | |
new_data[from_quintile] = new_data[from_quintile] - len(to_quintiles) * amount_to_transfer | |
return new_data | |
def poorest_give_to_richest(orig_data, gini_diff): | |
return transfer(orig_data, gini_diff, 0, [4]) | |
def poorest_give_to_everyone_equally(orig_data, gini_diff): | |
return transfer(orig_data, gini_diff, 0, [1,2,3,4]) | |
def everyone_gives_to_rich_equally(orig_data, gini_diff): | |
return transfer(orig_data, -gini_diff, 4, [0,1,2,3]) | |
def random_income_distribution(total_wealth=10000): | |
weights = [random.random() for _ in range(0, N_QUINTILES)] | |
return [int(total_wealth * w / sum(weights)) for w in weights].sort() | |
def graph(old_data, transfer_fn, gini_diffs, country, transfer_fn_name): | |
old_data = np.asarray(old_data) | |
traces = [ | |
go.Scatter( | |
x = [0,1,2,3,4,5], | |
y = [0] + list(old_data), | |
name = "Actual (2013)" | |
) | |
] | |
for gd in gini_diffs: | |
new_data = transfer_fn(old_data, gd) | |
traces.append(go.Scatter( | |
x = [0,1,2,3,4,5], | |
y = [0] + list(new_data), | |
name = "Gini increase: %.2f" % gd | |
)) | |
layout = go.Layout( | |
xaxis=dict(title="Quintile #"), | |
yaxis=dict(title="Fraction of income going to quintile"), | |
title="Change in income distribution for 2013 %s (%s)" % (country, transfer_fn_name) | |
) | |
fig = go.Figure(data=traces, layout=layout) | |
filename = "%s-%s.html" % (transfer_fn_name.lower().replace(" ", "-"), country) | |
plotly.offline.plot( | |
fig, | |
filename=filename, | |
) | |
US_2013_FRACTIONS = [ | |
0.051, | |
0.103, | |
0.154, | |
0.227, | |
0.464 | |
] | |
SWEDEN_2013_FRACTIONS = [ | |
0.086, | |
0.141, | |
0.177, | |
0.232, | |
0.364 | |
] | |
GINI_DIFFS = [0.01, 0.05, 0.1] | |
FRACTIONS = [ | |
('US', US_2013_FRACTIONS), | |
# ('Sweden', SWEDEN_2013_FRACTIONS) | |
] | |
TRANSFER_FNS = [ | |
(poorest_give_to_richest, "Poorest give to richest"), | |
(poorest_give_to_everyone_equally, "Poorest give to everyone"), | |
(everyone_gives_to_rich_equally, "Everyone give to rich") | |
] | |
for (country, data) in FRACTIONS: | |
for (transfer_fn, transfer_fn_name) in TRANSFER_FNS: | |
graph(data, transfer_fn, GINI_DIFFS, country, transfer_fn_name) | |
~ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment