Migration Data¶
To run the data generation for the migration data:
cd LEAP
python3 leap/data_generation/migration_data.py --time-delta P1Y
The --time-delta argument must be in ISO 8601 format:
ISO 8601 |
Meaning |
|---|---|
P1Y1M1DT1H1M1.1S |
1 year, 1 month, 1 day, 1 hour, 1 minute, 1 second, and 100 milliseconds |
P40D |
40 days |
P1Y1D |
1 year and 1 day |
P3DT4H59M |
3 days, 4 hours, and 59 minutes |
PT2H30M |
2 hours and 30 minutes |
P1M |
1 month |
PT1M |
1 minute |
Datasets¶
StatCan does not contain immigration/emigration data broken down by the necessary
groups (age, sex, etc), so we do not have exact data for this category. Instead, we use the
following data files:
leap/processed_data/life_table.csv(generated bydeath_data.py)leap/processed_data/birth/initial_population.csv(generated bybirth_data.py)
Initial Population Data¶
The initial_population.csv contains the number of people in a given age, sex,
province, and projection scenario, along with the number of births for that year. This data is the
net number of people, factoring in death, immigration, and emigration:
initial_population.csv
Column |
Type |
Description |
|---|---|---|
|
|
the date and time of the start of the time interval (e.g. |
|
|
the 2-letter province or territory ID
(e.g., |
|
|
age in years |
|
|
the proportion of births that are male |
|
|
number of people of the given age living in the given province during the given time interval |
|
|
number of births in the given province during the given time interval |
|
|
|
Life Table Data¶
The life_table.csv contains the probability of death at each timepoint for each age, sex,
province, and projection scenario.
Column |
Type |
Description |
|---|---|---|
|
|
the 2-letter province or territory ID
(e.g., |
|
|
|
|
|
the date and time of the start of the time interval (e.g. |
|
|
|
|
|
age in years |
|
|
the probability that a person of the given age, sex, province, and projection scenario at
the given timepoint will die during the time interval |
Data Processing¶
1. Load Life Table¶
First, we load the life tables from
processed_data/{time_delta_tag}/death/life_table_{province}.csv and concatenate them.
If we are using a time_delta less than that of the original data (1 year), we need to split
the ages into smaller intervals. Under the constant hazard rate assumption,
\(\mu(x, t)\) is constant over the time interval \([x, x + \Delta x_a)\),
where \(\Delta x_a\) is the age interval of the original data (1 year):
This means that the probability of death is constant over the time interval \([x, x + \Delta x_a)\):
We end up with:
Name |
Type |
Description |
|---|---|---|
|
|
The two-letter abbreviation of the province, e.g. |
|
|
|
|
|
The age of the person, in years. |
|
|
One of |
|
|
The starting timepoint of the interval during which the data was collected. |
|
|
The probability that a person of the given age and sex, living in the given province, will
die in the time interval |
Example: Life Table
|
|
|
|
|
|
|---|---|---|---|---|---|
BC |
LG |
0.00000 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
0.08333 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
… |
M |
2000-01-01 |
0.00565 |
BC |
LG |
0.91667 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
1.00000 years |
M |
2000-01-01 |
0.00687 |
BC |
LG |
… |
M |
2000-01-01 |
… |
BC |
LG |
110.91667 years |
M |
2000-01-01 |
1.000000 |
BC |
LG |
110.91667 years |
M |
2068-12-01 |
1.000000 |
BC |
LG |
0.00000 years |
F |
2000-01-01 |
0.00463 |
1. Load Population Data¶
First, we load the population data from
processed_data/{time_delta_tag}/birth/initial_population.csv.
If we are using a time_delta less than that of the original data (1 year), we need to split
the ages into smaller intervals. We assume that the population is uniformly distributed over the age
interval \([x, x + \Delta x_a)\):
For example, if we have:
|
|
|
|
|
|
|---|---|---|---|---|---|
BC |
LG |
0 |
M |
2000-01-01 |
1200 |
then this would become:
|
|
|
|
|
|
|---|---|---|---|---|---|
BC |
LG |
0.00000 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.083333 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.166667 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.250000 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.333333 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.416667 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.500000 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.583333 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.666667 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.750000 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.833333 years |
M |
2000-01-01 |
100 |
BC |
LG |
0.916667 years |
M |
2000-01-01 |
100 |
We end up with:
Name |
Type |
Description |
|---|---|---|
|
|
The two-letter abbreviation of the province, e.g. |
|
|
|
|
|
The age of the person, in years. |
|
|
One of |
|
|
The starting timepoint of the interval during which the data was collected. |
|
|
The number of people of the given age and sex, living in the given province, at the given timepoint, for the projection scenario. |
Example: Population Data
|
|
|
|
|
|
|---|---|---|---|---|---|
BC |
LG |
0.00000 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
0.08333 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
… |
M |
2000-01-01 |
0.00565 |
BC |
LG |
0.91667 years |
M |
2000-01-01 |
0.00565 |
BC |
LG |
1.00000 years |
M |
2000-01-01 |
0.00687 |
BC |
LG |
… |
M |
2000-01-01 |
… |
BC |
LG |
110.91667 years |
M |
2000-01-01 |
1.000000 |
BC |
LG |
110.91667 years |
M |
2068-12-01 |
1.000000 |
BC |
LG |
0.00000 years |
F |
2000-01-01 |
0.00463 |
3. Compute Net Migration¶
Let us define the notation:
To obtain the net migration, for anyone of age > 0, we compute the number of people in each age
group projected to die during that time interval based on the prob_death column in the
life_table.csv. Then we calculate the net change in people using the n column in the
initial_population.csv.
Solving for \(\Delta n_{\text{migration}}\) gives us the net migration during that time interval:
Example: Calculating Net Migration
For example, suppose we start with the following data:
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|
BC |
LG |
1.00000 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.083333 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.166667 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.250000 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.333333 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.416667 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.500000 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.583333 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.666667 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.750000 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.833333 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
1.916667 years |
M |
2000-01-01 |
100 |
0.000235 |
BC |
LG |
2.00000 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.083333 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.166667 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.250000 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.333333 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.416667 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.500000 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.583333 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.666667 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.750000 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.833333 years |
M |
2001-01-01 |
115 |
0.000369 |
BC |
LG |
2.916667 years |
M |
2001-01-01 |
115 |
0.000369 |
Then we would add an n_prev column and calculate the net change in people,
\(\Delta n_{\text{total}}\), using the n and n_prev columns:
delta_n = n - n_prev * (1 - prob_death)
|
|
|
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|---|---|---|
BC |
LG |
1.00000 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.083333 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.166667 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.250000 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.333333 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.416667 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.500000 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.583333 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.666667 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.750000 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.833333 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
1.916667 years |
M |
2000-01-01 |
100 |
nan |
0.000235 |
nan |
nan |
BC |
LG |
2.00000 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.083333 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.166667 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.250000 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.333333 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.416667 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.500000 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.583333 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.666667 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.750000 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
BC |
LG |
2.833333 years |
M |
2001-01-01 |
115 |
100 |
0.000235 |
0.000369 |
15.0235 |
BC |
LG |
2.916667 years |
M |
2001-01-01 |
115 |
100 |
0.000369 |
0.000235 |
15.0235 |
4. Convert the Age to Integer Years¶
Next, we convert the age back to integer years, by summing the number of migrants in each age interval \([x, x + \Delta x_a)\):
5. Compute Probability of Emigration¶
6. Compute Proportions of Migrants¶
We calculate the proportion of migrants of a given age, sex, province, and projection scenario, relative to the total number of births in that province and projection scenario:
Next we calculate the proportion of immigrants/emigrants of a given age, sex, province, and projection scenario at a given timepoint, relative to the total number of immigrants/emigrants in that province and projection scenario, at that timepoint:
leap.data_generation.migration_data module¶
- leap.data_generation.migration_data.get_delta_n(n: float, n_prev: float, prob_death: float) float[source]¶
Get the population change due to migration for a given age and sex in a single time interval.
- Parameters:¶
- n: float¶
The number of people living in Canada for a single age, sex, timepoint, province, and projection scenario.
- n_prev: float¶
The number of people living in Canada in the previous time interval for the same age, sex, province, and projection scenario as defined for
n. So ifnis the number of females aged10in the year2020,n_previs the number of females aged9in the year2019.- prob_death: float¶
The probability that a person with a given age and sex at a given timepoint will die between the previous timepoint and this timepoint. So if the person is a female aged
10in2020,prob_deathis the probability that a female aged9in2019will die by the age of10.
- Returns:¶
The change in population for a given timepoint, age, and sex due to migration.
- leap.data_generation.migration_data.convert_age_to_int(df: pandas.DataFrame, agg: dict[str, str], groupby_cols: list[str]) pandas.DataFrame[source]¶
Convert age values to integer years.
- Parameters:¶
- df: pandas.DataFrame¶
A dataframe containing an
agecolumn with age values which may be non-integer years.- agg: dict[str, str]¶
A dictionary specifying the aggregation method to use for other columns when grouping by integer age. The keys should be the column names, and the values should be the aggregation method to use for that column, e.g.
"sum"or"mean".- groupby_cols: list[str]¶
The columns to group by when converting age to integer. Should not include the
agecolumn, but should include all other columns which are needed to uniquely identify rows after grouping by integer age.
- Returns:¶
A dataframe with the same columns as the input dataframe, but with the
agecolumn converted to integer years. The values in the other columns are aggregated according to the specified aggregation methods when grouping by integer age.
- leap.data_generation.migration_data.load_mortality_data(time_delta: leap.utils.TimeDelta) pandas.DataFrame[source]¶
Load the mortality data for the given time delta.
- Parameters:¶
- time_delta: leap.utils.TimeDelta¶
The duration of time between subsequent data points.
- Returns:¶
timepoint: The timepoint which the data applies to.province: A string indicating the 2-letter province abbreviation, e.g."BC". For all of Canada, set province to"CA".age: The integer age.sex: One ofM= male,F= female.prob_death: The probability that a person with a given age and sex at a given timepoint will die between the previous timepoint and this timepoint.
- Return type:¶
A dataframe with the following columns
- leap.data_generation.migration_data.load_population_data(time_delta: leap.utils.TimeDelta) pandas.DataFrame[source]¶
Load the population data for the given time delta.
- Parameters:¶
- time_delta: leap.utils.TimeDelta¶
The duration of time between subsequent data points.
- Returns:¶
timepoint: The timepoint which the data applies to.province: A string indicating the 2-letter province abbreviation, e.g."BC". For all of Canada, set province to"CA".age: The integer age.sex: One ofM= male,F= female.n: The number of people living in Canada for a single age, sex, timepoint, province, and projection scenario.projection_scenario: The projection scenario.
- Return type:¶
A dataframe with the following columns
- leap.data_generation.migration_data.load_migration_data(df_population: pandas.DataFrame, life_table: pandas.DataFrame, time_delta: leap.utils.TimeDelta) pandas.DataFrame[source]¶
Generate migration data for the given provinces and years.
- Parameters:¶
- df_population: pandas.DataFrame¶
A dataframe containing the population data. Must have columns: *
timepoint (dt.datetime): The given timepoint. *province (str): The 2-letter province ID, e.g.BC. *age (int): The integer age. *sex (str): One ofM= male,F= female. *projection_scenario (str): The projection scenario abbreviation. *n (float): The number of people living in Canada for a single age, sex, timepoint,province, and projection scenario.
- life_table: pandas.DataFrame¶
A dataframe containing the life table data. Must have columns: *
timepoint (dt.datetime): The given timepoint. *province (str): The 2-letter province ID, e.g.BC. *age (int): The integer age. *sex (str): One ofM= male,F= female. *prob_death (float): The probability that a person with a given age and sex at agiven timepoint will die between the previous timepoint and this timepoint.
- time_delta: leap.utils.TimeDelta¶
The duration of time between subsequent data points.
- Returns:¶
timepoint: The timepoint which the data applies to.province: A string indicating the 2-letter province abbreviation, e.g."BC". For all of Canada, set province to"CA".sex: One ofM= male,F= female.age: The integer age.projection_scenario: The projection scenario.delta_n: The signed change in population for a given timepoint, age, sex, province, and projection scenario due to net migration. Positive values indicate net immigration; negative values indicate net emigration.prop_migrants_birth: The signed proportion ofdelta_nrelative to the total number of births in that time interval for the given province and projection scenario. Positive = net immigration, negative = net emigration.prop_immigrants_timepoint: For cells wheredelta_n > 0, the proportion of immigrants for this age and sex relative to the total number of immigrants in that time interval. Zero for emigration cells. Denominator includes only immigration cells.prop_emigrants_timepoint: For cells wheredelta_n < 0, the proportion of emigrants for this age and sex relative to the total number of emigrants in that time interval. Zero for immigration cells. Denominator includes only emigration cells.prob_emigration: For cells wheredelta_n < 0, the per-person probability of emigrating (abs(delta_n) / N). Zero for immigration cells.
- Return type:¶
A dataframe with the following columns
-
leap.data_generation.migration_data.generate_migration_data(time_delta: leap.utils.TimeDelta, to_csv: bool =
True) pandas.DataFrame | None[source]¶ Generate immigration/emigration data.
- Parameters:¶
- time_delta: leap.utils.TimeDelta¶
The duration of time between subsequent data points.
-
leap.data_generation.migration_data.plot(df: pandas.DataFrame, y: str, color: str, title: str =
'', ylabel: str ='', file_path: pathlib.Path | None =None, width: int =2000, height: int =1500)[source]¶ Plot the migration data for validation.
- Parameters:¶
- df: pandas.DataFrame¶
A dataframe containing the life table data. Must have columns:
timepoint (dt.datetime): The given timepoint.province (str): The 2-letter province ID, e.g.BC.age (int): The integer age.sex (str): One ofM= male,F= female.projection_scenario (str): The projection scenario abbreviation.
- y: str¶
The name of the column in the dataframe which will be plotted as the
ydata.- color: str¶
The name of the column in the dataframe which will be used to color the data.
- title: str =
''¶ The title of the plot.
- ylabel: str =
''¶ The label for the y-axis.
- file_path: pathlib.Path | None =
None¶ The path to save the plot to.
- width: int =
2000¶ The width of the plot.
- height: int =
1500¶ The height of the plot.