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