import starsim as ss
= dict(
pars = ss.peryear(20), # Annual crude birth rate (per 1000 people)
birth_rate = ss.peryear(15), # Annual crude death rate (per 1000 people)
death_rate = 'random',
networks = 'sir'
diseases
)= ss.Sim(pars) sim
T3 - Demographics
An interactive version of this notebook is available on Google Colab or Binder.
There are a few basic ways to add vital dynamics to your model, e.g.
This will apply annual birth and death rates as specified in the pars
dict. Alternatively, we can make demographic components, which achieves the same thing:
= [
demographics =ss.peryear(20)),
ss.Births(birth_rate=ss.peryear(15))
ss.Deaths(death_rate
]= ss.Sim(demographics=demographics) sim
You can even simply set demographics=True
to use default rates:
=True).run().plot(); ss.Sim(demographics
Initializing sim with 10000 agents
Running 2000.01.01 ( 0/51) (0.00 s) ———————————————————— 2%
Running 2010.01.01 (10/51) (0.01 s) ••••———————————————— 22%
Running 2020.01.01 (20/51) (0.02 s) ••••••••———————————— 41%
Running 2030.01.01 (30/51) (0.03 s) ••••••••••••———————— 61%
Running 2040.01.01 (40/51) (0.04 s) ••••••••••••••••———— 80%
Running 2050.01.01 (50/51) (0.05 s) •••••••••••••••••••• 100%
Figure(768x576)
By default, agents age if and only if at least one demographics module is included. You can override this behavior by setting use_aging
, e.g. ss.Sim(use_aging=False)
Scaling results to whole populations
Even though we’ve been simulating populations of a few thousand agents, we can also use the total_pop
parameter to scale our results so that they reflect a much larger population. You can think of this as a kind of statistical sampling approximation. If we want to model the population of Nigeria, for example, it would be much too computationally intensive to simulate 200 million agents. However, we could simulate 50,000 agents and then say that each agent represents 4,000 people. Again, we can do this by passing total_pop=200e6
to the sim or in the pars
dictionary. Here’s an example:
= [
demographics =ss.peryear(20)),
ss.Births(birth_rate=ss.peryear(15))
ss.Deaths(death_rate
]= ss.Sim(pars={'total_pop': 200e6, 'n_agents': 50e3}, demographics=demographics) sim
Using realistic vital demographics
For more realistic demographics, we can also pass in a file that has birth or death rates over time and by age/sex. There are examples of these files in the test_data
folder. Here’s how we would read them in and construct realistic vital dynamics for Nigeria:
import starsim as ss
import pandas as pd
import matplotlib.pyplot as plt
# Read in age-specific fertility rates
= pd.read_csv('test_data/nigeria_asfr.csv')
fertility_rates = ss.Pregnancy(fertility_rate=fertility_rates)
pregnancy
= pd.read_csv('test_data/nigeria_deaths.csv')
death_rates = ss.Deaths(death_rate=death_rates, rate_units=1)
death
= [pregnancy, death]
demographics
# Make people using the distribution of the population by age/sex in 1995
= 5_000
n_agents = 106819805 # Population of Nigeria in 1995, the year we will start the model
nga_pop_1995 = pd.read_csv('test_data/nigeria_age.csv')
age_data = ss.People(n_agents, age_data=age_data)
ppl
# Make the sim, run and plot
= ss.Sim(total_pop=nga_pop_1995, start=1995, people=ppl, demographics=demographics, networks='random', diseases='sir')
sim
sim.run()
# Read in a file with the actual population size
= pd.read_csv('test_data/nigeria_popsize.csv')
nigeria_popsize = nigeria_popsize[(nigeria_popsize.year >= 1995) & (nigeria_popsize.year <= 2030)]
data
# Plot the overall population size - simulated vs data
= plt.subplots(1, 1)
fig, ax = sim.results
res =0.5, label='Data')
ax.scatter(data.year, data.n_alive, alpha='k', label='Model')
ax.plot(sim.t.yearvec, res.n_alive, color
ax.legend()'Population')
ax.set_title( plt.show()
Initializing sim with 5000 agents
Running 1995.01.01 ( 0/51) (0.00 s) ———————————————————— 2%
Running 2005.01.01 (10/51) (0.18 s) ••••———————————————— 22%
Running 2015.01.01 (20/51) (0.30 s) ••••••••———————————— 41%
Running 2025.01.01 (30/51) (0.38 s) ••••••••••••———————— 61%
Running 2035.01.01 (40/51) (0.47 s) ••••••••••••••••———— 80%
Running 2045.01.01 (50/51) (0.56 s) •••••••••••••••••••• 100%
If you want to use realistic demographics for your model, you can adapt the data files and code snippet above to read in the relevant demographic data files for your country/setting.
Note: In the code block above, we set the units of the mortality data to 1, as opposed to 1/1000. If your data come in the form of deaths per 1000 people, set units to 1/1000. Note also that as per standard definitions, fertility_rate
is defined per woman, whereas birth_rate
is defined per person.
Exercises
- In Niger, the crude birth rate is 45 and the crude death rate is 9. Assuming these rates stay constant, and starting with a total population of 24 million in 2020, how many people will there be in 2040? (You do not need to include any diseases in your model.)