Life tables¶
While some life tables are included in the miscore.processes.oc.data module, you might want to use a custom life table to initialize the OC process.
In this tutorial, it will be shown how to do this.
Single life table¶
First, let’s implement a single life table for both males and females. Life tables are often represented by the number of people alive at a certain age, given a base population of usually 100,000 individuals. These tables can be converted to the fraction of the population that died before reaching a certain age. Both representations are given in the table below. The “Fraction died” column is essentially a cumulative distribution function that can be used to draw random ages at which individuals will die in the simulation.
Age |
People alive |
Fraction died |
|---|---|---|
0 |
100,000 |
0.000 |
25 |
99,000 |
0.010 |
50 |
97,500 |
0.025 |
75 |
65,000 |
0.450 |
100 |
0 |
1.000 |
The OC process expects each life table to be a variable with which a PiecewiseLinear instance can be constructed.
The x-values should be the cumulative distribution function as described above, and the y-values should be the corresponding ages.
The example below shows how to create such a variable and how to use it to initialize an OC process.
from miscore.processes import OC
life_table = (
(0.000, 0),
(0.010, 25),
(0.025, 50),
(0.450, 75),
(1.000, 100)
)
oc = OC(
life_table=life_table
)
The oc variable now holds the initialized OC process and can be included in one or more Universe instances.
Truncate life table¶
Sometimes you want to truncate your life tables.
If you’re only interested in the model outcomes between age 60 and 80, it could be efficient if no one dies of other causes
before 60.
Also it could speed up your simulations if everyone dies at age 80, when your window of interest has ended.
This can be done by truncating the life table by using the start_age and end_age arguments.
from miscore.processes import OC
life_table = (
(0.000, 0),
(0.010, 25),
(0.025, 50),
(0.450, 75),
(1.000, 100)
)
oc = OC(
life_table=life_table,
start_age=60,
end_age=80
)
Now nobody dies of other causes before 60 and everybody that survives until 80 will die of other causes at 80.
Note that the OC process also has an end_year argument: the life table is then truncated at a certain year.
Sex-specific life tables¶
Tip
Consider creating a separate cohort (Run a population model) for each sex instead.
Obviously, in many scenarios we want to use separate life tables for males and females. Let’s assume the following life tables.
Age |
Fraction died (male) |
Fraction died (female) |
|---|---|---|
0 |
0.000 |
0.000 |
25 |
0.010 |
0.005 |
50 |
0.025 |
0.020 |
75 |
0.450 |
0.425 |
100 |
1.000 |
1.000 |
In MISCore, we can create these tables and use them to initialize the OC process as follows.
from miscore.processes import OC
life_table_male = (
(0.000, 0),
(0.010, 25),
(0.025, 50),
(0.450, 75),
(1.000, 100)
)
life_table_female = (
(0.000, 0),
(0.005, 25),
(0.020, 50),
(0.425, 75),
(1.000, 100)
)
oc = OC(
life_table_male=life_table_male,
life_table_female=life_table_female
)
Adjusting for disease-specific mortality¶
In the case of highly prevalent cancers, the disease we want to model may actually be the cause of
a significant part of the mortality reported by our life tables. To use raw life tables would then
be an overestimation of the mortality rates of our population, since we are exposing them twice to
our disease-specific mortality. We can adjust for this by using rate_to_life_table(),
which converts mortality rates per age group to life table inputs for OC, and has
the option of adding additional cause-specific mortality rates which are first subtracted from our raw mortality rates.
For example, we may want to model a terrible disease that causes half of all mortality in our population,
but we only have the total mortality rates. We may pass rate_to_life_table()
a List with the total mortality rates first, and then the cause-specific mortality rate to get an adjusted life table:
from miscore.processes import OC
from miscore.processes.oc import rate_to_life_table
total_mortality_rates = (
(0.000, 0),
(0.002, 20),
(0.004, 40),
(0.010, 60),
(0.015, 80),
)
specific_mortality_rates = (
(0.000, 0),
(0.001, 20),
(0.002, 40),
(0.005, 60),
(0.0075, 80),
)
net_life_table = rate_to_life_table(
rate_tables = [total_mortality_rates, specific_mortality_rates]
)
oc = OC(
life_table = net_life_table
)
Note that for simultaneous modelling of several diseases, rate_to_life_table may be passed
a list of specific mortality rate tables, so long as the all-cause mortality rates are passed as the first element of the List.
Cohort-specific life tables¶
For the US and the Netherlands, MISCore also includes life tables that are specific to the birth cohort as well as the sex.
These life tables can be imported with the function get_cohort_table(). For example, if we want to
get the life tables for males in the 5-year cohorts between 1940 and 1960 for the Netherlands:
from miscore.processes.oc.data import get_cohort_table
cohort_tables = get_cohort_table(
country="NL",
sex="male",
interval=5,
cohorts=[1940, 1945, 1950, 1955]
)
We can also adjust these cohort-specific life tables for our diseases specific mortality rates by passing the previously specified table of rates:
specific_mortality_rates = [
(0.001, 50),
(0.002, 70),
(0.003, 90)
]
cohort_tables = get_cohort_table(
country="NL",
sex="male",
interval=5,
cohorts=[1940, 1945, 1950, 1955],
specific_rate_tables=[specific_mortality_rates]
)
If our disease specific mortality data is also available by sex and cohort, we may also supply a dictionary of cause-specific rates:
specific_mortality_rates_m_1940 = [
(0.001, 50),
(0.002, 70),
(0.003, 90)
]
specific_mortality_rates_m_1945 = [
(0.003, 50),
(0.002, 70),
(0.001, 90)
]
cohort_tables = get_cohort_table(
country="NL",
sex="male",
interval=5,
cohorts=[1940, 1945],
specific_rate_tables={
"male": {
1940: [specific_mortality_rates_m_1940],
1945: [specific_mortality_rates_m_1945]
}
}
)
The default mortality rates supplied by get_cohort_table() are the period mortality rates. These report the age-specific rate of mortality
that was contemporary to the particular year of birth of our cohort. It will often be more accurate to use the generation life tables instead, which use the measured
and predicted age-specific mortality rates of the cohort over time, and can be obtained by setting cohort_table to True:
cohort_tables = get_cohort_table(
country="NL",
sex="male",
interval=5,
cohorts=[1940, 1945, 1950, 1955],
cohort_table=True
)