Calculating Indices: SRI, SCAI, and GAI¶

In this notebook, we will calculate the Stroke Risk Index (SRI), Stroke Care Access Index (SCAI), and Geographic Accessibility Index (GAI), using predefined variables.

Reading Data from Database and Importing Index Pipeline¶

In [1]:
# Importing packages

import sqlite3
import pandas as pd
import sys
In [2]:
sys.path.insert(0, "../src")
In [3]:
# Importing pipeline
from index_pipeline import build_index
In [4]:
con = sqlite3.connect("../data/stroke_burden.db")
In [5]:
df = pd.read_sql("SELECT * FROM master", con)
In [6]:
# Creating SCAI dataframe
#
# hospitals_per_100k and stroke_centers_per_100k are excluded from the index
# (kept in EDA) and pcnt_insured enters as the uninsured rate — see
# docs/DECISIONS.md (2026-07-06).

scai = df[[
    "fips",
    "hospital_beds_per_100k",
    "pcp_per_100k",
    "neurologists_per_100k",
    "pcnt_insured"
]].copy()

# Recast insurance coverage as the uninsured rate: right-skewed, so log1p
# applies; higher = worse access, so it gets flipped in build_index below.
scai["pcnt_uninsured"] = 100 - scai["pcnt_insured"]
In [7]:
# Creating GAI dataframe

gai = df[[
    "fips",
    "drive_time_min",
    "drive_time_advanced",
    "nearest_stroke_distance",
    "nearest_stroke_distance_advanced"
]].copy()
In [8]:
# Creating SRI dataframe

sri = df[[
    "fips",
    "pop_density",
    "pcnt_65_plus",
    "poverty_rate",
    "pcnt_low_income",
    "pcnt_bachelors",
    "smoking_prevalence",
    "obesity_prevalence",
    "diabetes_prevalence",
    "physical_inactivity",
    "hypertension_prevalence",
    "high_cholesterol_prevalence",
    "binge_drinking_prevalence",
    "stroke_prevalence"
]].copy()

Building Indices¶

SCAI¶

In [9]:
scai_result = build_index(
    scai,
    [
        "hospital_beds_per_100k",
        "pcp_per_100k",
        "neurologists_per_100k",
        "pcnt_uninsured"
    ],
    flip=["pcnt_uninsured"],
    transforms={"pcnt_uninsured": "log1p"},
    name="scai"
)

df["scai"] = scai_result.scores
In [10]:
scai_result.explained_variance_ratio
Out[10]:
0.5394857770201571
In [11]:
scai_result.loadings
Out[11]:
hospital_beds_per_100k    0.518748
pcp_per_100k              0.610016
neurologists_per_100k     0.594107
pcnt_uninsured            0.076270
Name: scai_pc1_loading, dtype: float64
In [12]:
# Skew check: should be empty — any variable listed here has |skew| > 2
# without a transform and needs a decision (see docs/DECISIONS.md)
scai_result.high_skew
Out[12]:
['neurologists_per_100k']

GAI¶

In [13]:
gai_result = build_index(
    gai,
    [
        "drive_time_min",
        "drive_time_advanced",
        "nearest_stroke_distance",
        "nearest_stroke_distance_advanced"
    ],
    flip=[
        "drive_time_min",
        "drive_time_advanced",
        "nearest_stroke_distance",
        "nearest_stroke_distance_advanced"
    ],
    transforms={
        "drive_time_min":"log1p",
        "drive_time_advanced":"log1p",
        "nearest_stroke_distance":"log1p",
        "nearest_stroke_distance_advanced":"log1p"
    },
    name="gai"
)

df["gai"] = gai_result.scores
In [14]:
gai_result.explained_variance_ratio
Out[14]:
0.7706484916219887
In [15]:
gai_result.loadings
Out[15]:
drive_time_min                      0.487536
drive_time_advanced                 0.508339
nearest_stroke_distance             0.505386
nearest_stroke_distance_advanced    0.498483
Name: gai_pc1_loading, dtype: float64

SRI¶

In [16]:
sri_result = build_index(
    sri,
    [
        "pop_density",
        "pcnt_65_plus",
        "poverty_rate",
        "pcnt_low_income",
        "pcnt_bachelors",
        "smoking_prevalence",
        "obesity_prevalence",
        "diabetes_prevalence",
        "physical_inactivity",
        "hypertension_prevalence",
        "high_cholesterol_prevalence",
        "binge_drinking_prevalence",
        "stroke_prevalence"
    ],
    flip=["pcnt_bachelors"],
    transforms={"pop_density": "log1p"},
    name="sri"
)
In [17]:
sri_result.explained_variance_ratio
Out[17]:
0.5223875266272114
In [18]:
sri_result.loadings
Out[18]:
pop_density                   -0.220684
pcnt_65_plus                   0.155486
poverty_rate                   0.245481
pcnt_low_income                0.325243
pcnt_bachelors                 0.351806
smoking_prevalence             0.361232
obesity_prevalence             0.296924
diabetes_prevalence            0.294431
physical_inactivity            0.297536
hypertension_prevalence        0.324855
high_cholesterol_prevalence    0.064245
binge_drinking_prevalence     -0.004078
stroke_prevalence              0.365741
Name: sri_pc1_loading, dtype: float64