Overview G Core Inequality S Composite Scoring H Harmonization DataFrames CLI Reference
Docs / Core Engines / DataFrames

DataFrame & Vulnerability Helpers

The moveq_core.frames module provides high-level DataFrame functions for computing composite demographic vulnerability indices and identifying multiply-deprived spatial cohorts.

Optional Dependency Extra
To keep moveq-core ultra-lightweight and zero-bloat, DataFrame helpers require the frames extra:
pip install "moveq-core[frames]" (or pip install "moveq[frames]").

1. Vulnerability Index (compute_vulnerability_index)

Normalizes any number of socio-demographic indicators (e.g. % households without a car, % elderly residents, % job seekers) using min-max feature scaling into \([0.0, 1.0]\) and calculates an equal-weighted composite 0-100 vulnerability series:

V_i = \frac{100}{K} \sum_{k=1}^K \frac{x_{ik} - \min(x_k)}{\max(x_k) - \min(x_k)}

Python Code Example

vulnerability_calc.py Python 3.10+
import pandas as pd
from moveq_core.frames import compute_vulnerability_index

df = pd.DataFrame({
    "zone_id": ["Z1", "Z2", "Z3", "Z4"],
    "no_car_pct": [12.0, 45.0, 22.0, 68.0],
    "elderly_pct": [10.0, 18.0, 25.0, 12.0],
    "unemployment_pct": [3.2, 8.5, 4.1, 14.2]
})

df["vulnerability_score"] = compute_vulnerability_index(
    df,
    factors=["no_car_pct", "elderly_pct", "unemployment_pct"]
)

print(df[["zone_id", "vulnerability_score"]])
# Returns pandas.Series with 0.0 - 100.0 index scores

2. Identify Multiply-Deprived Zones (identify_multiply_deprived)

Flags spatial zones that simultaneously fall into the worst tertile (top 33.3% most vulnerable) across multiple socio-demographic deprivation indicators:

deprivation_flags.py Python 3.10+
from moveq_core.frames import identify_multiply_deprived

# Flag rows in the worst tertile for at least 2 out of 3 factors
df["is_multiply_deprived"] = identify_multiply_deprived(
    df,
    factors=["no_car_pct", "elderly_pct", "unemployment_pct"],
    min_factors=2
)

print(df[["zone_id", "is_multiply_deprived"]])
# Returns boolean Series (True for high-priority equity investment zones)

3. GeoPandas & GIS Integration

Because moveq_core.frames operates on standard pandas DataFrames, it integrates seamlessly with geopandas.GeoDataFrame and spatial polygon geometry:

gis_pipeline.py GeoPandas + moveq
import geopandas as gpd
from moveq_core.frames import compute_vulnerability_index
from moveq import compute_gini

# 1. Load census boundary shapefile / GeoPackage
gdf = gpd.read_file("census_tracts.gpkg")

# 2. Compute vulnerability index column
gdf["vuln_index"] = compute_vulnerability_index(
    gdf, factors=["no_vehicle", "low_income_pct", "disability_pct"]
)

# 3. Compute overall service Gini on the GeoDataFrame
gini = compute_gini(gdf["bus_trips"].values, gdf["population"].values)
print(f"Regional Transit Gini: {gini:.4f}")