Using lost_years¶
Each of the three lookups appends its columns to your DataFrame and returns a *_match_status column saying whether the question could be answered at all.
import pandas as pd
from lost_years import lost_years_hld, lost_years_ssa, lost_years_who
The input¶
One row per person, with the year, country, age and sex.
data = [
{"year": 2019, "country": "USA", "age": 0, "sex": "M"},
{"year": 2020, "country": "USA", "age": 0, "sex": "M"},
{"year": 2019, "country": "JPN", "age": 65, "sex": "F"},
{"year": 2019, "country": "IND", "age": 30, "sex": "M"},
]
df = pd.DataFrame(data)
df
| year | country | age | sex | |
|---|---|---|---|---|
| 0 | 2019 | USA | 0 | M |
| 1 | 2020 | USA | 0 | M |
| 2 | 2019 | JPN | 65 | F |
| 3 | 2019 | IND | 30 | M |
HLD: international life tables¶
hld_year1/hld_year2 give the period the matched life table covers, hld_age/hld_age_interval the age interval it was read off, and hld_n_candidates how many equally eligible tables the tie-break had to choose between.
The first two rows are the US male life expectancy at birth that NCHS published for 2019 and 2020 – the 2.12-year COVID drop.
hld = lost_years_hld(df)
hld[
[
"country",
"year",
"age",
"sex",
"hld_life_expectancy",
"hld_year1",
"hld_year2",
"hld_age",
"hld_age_interval",
"hld_n_candidates",
"hld_match_status",
]
]
| country | year | age | sex | hld_life_expectancy | hld_year1 | hld_year2 | hld_age | hld_age_interval | hld_n_candidates | hld_match_status | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | USA | 2019 | 0 | M | 76.31 | 2019 | 2019 | 0 | 1 | 1 | ok |
| 1 | USA | 2020 | 0 | M | 74.19 | 2020 | 2020 | 0 | 1 | 1 | ok |
| 2 | JPN | 2019 | 65 | F | 24.63 | 2019 | 2019 | 65 | 1 | 1 | ok |
| 3 | IND | 2019 | 30 | M | 42.22 | 2016 | 2020 | 30 | 5 | 2 | ok |
India’s 2019 answer comes from a 2016-2020 period table read at the abridged interval [30, 35), and two equally eligible tables covered it. A country-year that no table covers at all gets no estimate; year_tolerance reaches to the nearest period and records how far it reached.
lebanon = pd.DataFrame(
{
"country": ["LBN", "LBN"],
"year": [1997, 1997],
"sex": ["F", "F"],
"age": [49, 49],
}
)
pd.concat(
[
lost_years_hld(lebanon.head(1)),
lost_years_hld(lebanon.tail(1), year_tolerance=5),
]
)[
[
"country",
"year",
"hld_life_expectancy",
"hld_year1",
"hld_year2",
"hld_match_status",
]
]
| country | year | hld_life_expectancy | hld_year1 | hld_year2 | hld_match_status | |
|---|---|---|---|---|---|---|
| 0 | LBN | 1997 | None | None | None | no eligible life table covering year |
| 1 | LBN | 1997 | 31.99 | 1998 | 1998 | ok: nearest period, 1 year(s) away |
HLD also carries regions, urban/rural splits, ethnic groups and socio-demographic groups. They are opt-in, because including them means more output rows than input rows.
sub = lost_years_hld(df.head(1), subpopulations=True)
len(sub) # rows returned for one input row
57
sub[["hld_region", "hld_ethnicity", "hld_life_expectancy", "hld_ref_id"]].head(8)
| hld_region | hld_ethnicity | hld_life_expectancy | hld_ref_id | |
|---|---|---|---|---|
| 0 | 0 | 0 | 76.31 | 3565.01 |
| 0 | 0 | E220 | 79.05 | 3565.02 |
| 0 | 0 | E230 | 76.33 | 3565.03 |
| 0 | 0 | E240 | 71.31 | 3565.04 |
| 0 | 0 | E330 | 68.62 | 3565.05 |
| 0 | 0 | E340 | 83.42 | 3565.06 |
| 0 | 10 | 0 | 72.23 | 3566.01 |
| 0 | 100 | 0 | 76.26 | 3566.1 |
SSA: the US period life table¶
The package ships the 2022 table, so years more than five years away return nothing rather than the 2022 figure.
us = pd.DataFrame(
{"age": [0, 30, 65], "sex": ["M", "M", "F"], "year": [2022, 2022, 2022]}
)
lost_years_ssa(us)
| age | sex | year | ssa_age | ssa_year | ssa_life_expectancy | ssa_match_status | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | M | 2022 | 0 | 2022 | 74.74 | ok |
| 1 | 30 | M | 2022 | 30 | 2022 | 46.51 | ok |
| 2 | 65 | F | 2022 | 65 | 2022 | 20.12 | ok |
stale = pd.DataFrame({"age": [30], "sex": ["M"], "year": [1900]})
lost_years_ssa(stale)
No SSA match: closest available value 2022 is more than 5.0 from 1900
| age | sex | year | ssa_age | ssa_year | ssa_life_expectancy | ssa_match_status | |
|---|---|---|---|---|---|---|---|
| 0 | 30 | M | 1900 | None | None | None | closest available value 2022 is more than 5.0 ... |
WHO: life expectancy at birth¶
The packaged WHO indicator has no age dimension, so there is no age input and the column is named for what it holds.
lost_years_who(df)[
[
"country",
"year",
"sex",
"who_year",
"who_life_expectancy_at_birth",
"who_match_status",
]
]
| country | year | sex | who_year | who_life_expectancy_at_birth | who_match_status | |
|---|---|---|---|---|---|---|
| 0 | USA | 2019 | M | 2019 | 76.533531 | ok |
| 1 | USA | 2020 | M | 2020 | 74.381893 | ok |
| 2 | JPN | 2019 | F | 2019 | 87.152152 | ok |
| 3 | IND | 2019 | M | 2019 | 69.175220 | ok |