In [1]:
# First, we'll load some modules that we're going to need
%matplotlib inline
import pysimpactcyan
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as stats
import numpy as np
In [2]:
# Create an instance of the PySimpactCyan class, which we can then use to run simulations
simpact = pysimpactcyan.PySimpactCyan()
In [3]:
# This is a helper function that runs a simulation, analyzes the generated data
# and creates a plot from it: a point in the figure indicates a relationship,
# the X-axis is the age of the man when the relationship was formed and the Y-axis
# is the relationship of the woman. A line is also fitted to these formed
# relationships and is shown as a red line. The green line is just the diagonal:
# if everyone formed relationships only with people of the same age, all points
# would lie on this green line.
def showAges(cfg, path="/tmp/simptest", seed=-1):
ret = simpact.run(cfg, path, seed=seed)
rel = pd.read_csv(ret["logrelations"])
ppl = pd.read_csv(ret["logpersons"])
numRel = rel.shape[0]
agesMen = []
agesWomen = []
for r in range(numRel):
idm = rel.iloc[r]["ID1"]
idw = rel.iloc[r]["ID2"]
t = rel.iloc[r]["FormTime"]
tobm = float(ppl[ppl["ID"] == idm]["TOB"])
tobw = float(ppl[ppl["ID"] == idw]["TOB"])
agesMen.append(t-tobm)
agesWomen.append(t-tobw)
plt.figure(1, figsize=(6,6), dpi=80)
plt.gca().set_aspect('equal')
plt.xlabel("Age man")
plt.ylabel("Age woman")
plt.plot(agesMen, agesWomen, 'o')
plt.plot([0,100],[0,100]) # Plot the diagonal
# Also perform a linear fit and plot the line
slope, intercept, r_value, p_value, std_err = stats.linregress(agesMen, agesWomen)
x = np.array([0,100])
y = x*slope + intercept
plt.plot(x,y)
print("")
print("Slope = {}, Intercept = {}".format(slope, intercept))
In [4]:
# First, we'll run a simulation with all the default settings. This uses
# the 'simple' formation hazard with settings that do not specify any
# particular age difference.
showAges(None);
In [5]:
# Next, we're going to run a simulation with the 'agegap' hazard. By default
# the preferred age gap is 0, and by controlling 'formation.hazard.agegap.gap_factor_man'
# and 'formation.hazard.agegap.gap_factor_woman' we can control the width of the
# resulting distribution. Using the settings below, only relationships in which
# both partners have approximately the same age will be formed.
cfg = {}
cfg["population.simtime"] = 50
cfg["population.nummen"] = 200
cfg["population.numwomen"] = 200
cfg["formation.hazard.type"] = "agegap"
cfg["formation.hazard.agegap.baseline"] = 0
cfg["formation.hazard.agegap.gap_factor_man"] = -0.3
cfg["formation.hazard.agegap.gap_factor_woman"] = -0.3
showAges(cfg);
In [6]:
# This is nearly the same simulation as the previous one, but here the
# weight of the agegap term is different, resulting in a broader
# distribution.
cfg = {}
cfg["population.simtime"] = 50
cfg["population.nummen"] = 200
cfg["population.numwomen"] = 200
cfg["formation.hazard.type"] = "agegap"
cfg["formation.hazard.agegap.baseline"] = 0
cfg["formation.hazard.agegap.gap_factor_man"] = -0.075
cfg["formation.hazard.agegap.gap_factor_woman"] = -0.075
showAges(cfg);
In [7]:
# In the following simulation, we'll use the settings for the narrower
# distribution again, but we'll also specify a preferred age gap of 15
# years, both for men and for women. This will cause the distribution to
# be offset from the diagonal
cfg = {}
cfg["population.simtime"] = 50
cfg["population.nummen"] = 200
cfg["population.numwomen"] = 200
cfg["formation.hazard.type"] = "agegap"
cfg["formation.hazard.agegap.baseline"] = 0
cfg["formation.hazard.agegap.gap_factor_man"] = -0.3
cfg["formation.hazard.agegap.gap_factor_woman"] = -0.3
cfg["person.agegap.man.dist.fixed.value"] = 15
cfg["person.agegap.woman.dist.fixed.value"] = 15
showAges(cfg);
In [8]:
# Finally, using 'formation.hazard.agegap.gap_agescale_man' and
# 'formation.hazard.agegap.gap_agescale_woman', the preferred age difference
# becomes age dependent, and the slope of the resulting distribution will
# clearly be different than the one of the green line.
cfg = {}
cfg["population.simtime"] = 50
cfg["population.nummen"] = 200
cfg["population.numwomen"] = 200
cfg["formation.hazard.type"] = "agegap"
cfg["formation.hazard.agegap.baseline"] = 0
cfg["formation.hazard.agegap.gap_factor_man"] = -0.3
cfg["formation.hazard.agegap.gap_agescale_man"] = 0.3
cfg["formation.hazard.agegap.gap_factor_woman"] = -0.3
cfg["formation.hazard.agegap.gap_agescale_woman"] = 0.3
showAges(cfg);
In [ ]: