Worked examples of Gini, Palma, and the Concentration Index on arrays you already have. moveq does not parse GTFS, aggregate to H3, route, or render maps: those belong in the tools that produce the arrays.
The same pattern as examples/basic_equity/run.py. Service is the resource; population is the weight; rank is a socioeconomic ordering you must declare.
import numpy as np
from moveq import compute_gini, compute_palma_ratio, compute_concentration_index
service = np.array([10.0, 20.0, 5.0, 50.0, 8.0])
population = np.array([1000, 800, 1200, 300, 900])
deprivation_rank = np.array([1, 3, 2, 5, 4]) # 1 = most deprived; higher = more advantaged
gini = compute_gini(service, population)
palma = compute_palma_ratio(service, population)
ci = compute_concentration_index(
service, deprivation_rank, population,
rank_direction="higher_is_advantaged",
)
print(f"Gini: {gini:.4f}")
print(f"Palma ratio: {palma:.4f}")
print(f"Concentration Index: {ci:.4f}")
Compare two service arrays on the same units and rank. Interpretation, and any regulatory determination, rest with the analyst. moveq generates evidence; it does not determine compliance.
from moveq import compute_concentration_index
# Rank: 1 = most deprived, higher = more advantaged
rank = tract_df["deprivation_rank"].values
baseline_service = tract_df["trips_2025"].values
proposed_service = tract_df["trips_2026_proposed"].values
population = tract_df["population"].values
ci_baseline = compute_concentration_index(
baseline_service, rank, population,
rank_direction="higher_is_advantaged",
)
ci_proposed = compute_concentration_index(
proposed_service, rank, population,
rank_direction="higher_is_advantaged",
)
print(f"Baseline CI: {ci_baseline:+.4f}")
print(f"Proposed CI: {ci_proposed:+.4f}")
print(f"Change in CI: {ci_proposed - ci_baseline:+.4f}")