public

  • Download Gist
population-portugal.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
import numpy as np
from matplotlib import pyplot as plt
 
#### From XKCD plot generator
"""
XKCD plot generator
-------------------
Author: Jake Vanderplas
 
This is a script that will take any matplotlib line diagram, and convert it
to an XKCD-style plot. It will work for plots with line & text elements,
including axes labels and titles (but not axes tick labels).
 
The idea for this comes from work by Damon McDougall
http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg25499.html
"""
import numpy as np
import pylab as pl
from scipy import interpolate, signal
import matplotlib.font_manager as fm
 
 
# We need a special font for the code below. It can be downloaded this way:
import os
import urllib2
if not os.path.exists('Humor-Sans.ttf'):
fhandle = urllib2.urlopen('http://antiyawn.com/uploads/Humor-Sans.ttf')
open('Humor-Sans.ttf', 'w').write(fhandle.read())
 
def xkcd_line(x, y, xlim=None, ylim=None,
mag=1.0, f1=30, f2=0.05, f3=15):
"""
Mimic a hand-drawn line from (x, y) data
 
Parameters
----------
x, y : array_like
arrays to be modified
xlim, ylim : data range
the assumed plot range for the modification. If not specified,
they will be guessed from the data
mag : float
magnitude of distortions
f1, f2, f3 : int, float, int
filtering parameters. f1 gives the size of the window, f2 gives
the high-frequency cutoff, f3 gives the size of the filter
Returns
-------
x, y : ndarrays
The modified lines
"""
x = np.asarray(x)
y = np.asarray(y)
# get limits for rescaling
if xlim is None:
xlim = (x.min(), x.max())
if ylim is None:
ylim = (y.min(), y.max())
 
if xlim[1] == xlim[0]:
xlim = ylim
if ylim[1] == ylim[0]:
ylim = xlim
 
# scale the data
x_scaled = (x - xlim[0]) * 1. / (xlim[1] - xlim[0])
y_scaled = (y - ylim[0]) * 1. / (ylim[1] - ylim[0])
 
# compute the total distance along the path
dx = x_scaled[1:] - x_scaled[:-1]
dy = y_scaled[1:] - y_scaled[:-1]
dist_tot = np.sum(np.sqrt(dx * dx + dy * dy))
 
# number of interpolated points is proportional to the distance
Nu = int(200 * dist_tot)
u = np.arange(-1, Nu + 1) * 1. / (Nu - 1)
 
# interpolate curve at sampled points
k = min(3, len(x) - 1)
res = interpolate.splprep([x_scaled, y_scaled], s=0, k=k)
x_int, y_int = interpolate.splev(u, res[0])
 
# we'll perturb perpendicular to the drawn line
dx = x_int[2:] - x_int[:-2]
dy = y_int[2:] - y_int[:-2]
dist = np.sqrt(dx * dx + dy * dy)
 
# create a filtered perturbation
coeffs = mag * np.random.normal(0, 0.01, len(x_int) - 2)
b = signal.firwin(f1, f2 * dist_tot, window=('kaiser', f3))
response = signal.lfilter(b, 1, coeffs)
 
x_int[1:-1] += response * dy / dist
y_int[1:-1] += response * dx / dist
 
# un-scale data
x_int = x_int[1:-1] * (xlim[1] - xlim[0]) + xlim[0]
y_int = y_int[1:-1] * (ylim[1] - ylim[0]) + ylim[0]
return x_int, y_int
 
#### End copy & paste
 
 
in2011 = np.array([
539491,
537521,
579590,
688686,
790901,
814661,
761457,
770781,
728518,
686134,
642516,
571452,
550916,
538165,
453962,
701366,
], dtype=float)
 
brate = in2011[0]/in2011[4:8].sum()
drate = in2011[0]/in2011[-1:].sum()
population = [in2011.sum()]
rate = in2011[-3:].sum()/float(in2011[4:8].sum())
rates = [rate]
 
steps = 20
 
for i in xrange(steps):
old = in2011[-1]
in2011[1:] = in2011[:-1]
in2011[0] = brate * in2011[4:8].sum()
in2011[-1] += (1.-drate)*old
rate = in2011[-3:].sum()/float(in2011[4:8].sum())
rates.append(rate)
population.append(in2011.sum())
 
population = np.array(population)
rates = np.array(rates)
years = 2011.+np.arange(0,5*steps+1,5)
years_,population = xkcd_line(years, population/1000./1000.)
plt.plot(years_, population, 'r', lw=3)
plt.xlabel('Year')
plt.ylabel('Population (in millions)')
ax2 = plt.twinx()
years_,rates = xkcd_line(years, rates)
ax2.plot(years_, rates, 'b', lw=3)
ax2.set_ylabel('Dependency ratio')
plt.savefig('population.png')
 
 
 
brate = [
24.1, 24.4, 24.5, 23.5, 24.0, 23.4, 23.2, 22.8, 22.1, 21.7, 20.8, 21.0, 20.2,
20.0, 19.6, 19.8, 20.0, 19.1, 17.5, 16.6, 16.2, 15.4, 15.2, 14.5, 14.3, 13.0,
12.6, 12.3, 12.2, 11.8, 11.7, 11.7, 11.5, 11.4, 10.9, 10.7, 11.0, 11.2, 11.2,
11.4, 11.7, 11.0, 11.0, 10.8, 10.4, 10.4, 10.0, 9.7, 9.8, 9.4, 9.6, 9.2]
 
 
plt.clf()
plt.xlabel('year')
plt.ylabel('fertility rate')
years = np.arange(1960,1960+len(brate))
years_, brate = xkcd_line(years, brate)
plt.plot(years_, brate, 'r', lw=3)
plt.savefig('fertility.png')

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.