Skip to content

Instantly share code, notes, and snippets.

@robert
Created March 11, 2018 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robert/7eee027244f81523e57b1f3df32cb6a2 to your computer and use it in GitHub Desktop.
Save robert/7eee027244f81523e57b1f3df32cb6a2 to your computer and use it in GitHub Desktop.
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