Single-group Segregation Indices¶
%load_ext watermark
%watermark -a 'eli knaap' -v -d -u -p segregation,geopandas,libpysal
Author: eli knaap
Last updated: 2026-09-04
Python implementation: CPython
Python version : 3.14.7
IPython version : 9.17.1
segregation: 2.5.6.dev83+g2e095ced1
geopandas : 1.1.4
libpysal : 4.15.0
Single-group indices are calculated using the singlegroup module
Data Prep¶
import geopandas as gpd
import matplotlib.pyplot as plt
from libpysal.examples import load_example
# read in sacramento data from libpysal and reproject into an appropriate CRS
sacramento = gpd.read_file(load_example("Sacramento1").get_path("sacramentot2.shp"))
sacramento = sacramento.to_crs(sacramento.estimate_utm_crs())
Downloading Sacramento1 to /home/runner/.local/share/pysal/Sacramento1
sacramento.head()
| FIPS | MSA | TOT_POP | POP_16 | POP_65 | WHITE | BLACK | ASIAN | HISP | MULTI_RA | ... | EMP_FEM | OCC_MAN | OCC_OFF1 | OCC_INFO | HH_INC | POV_POP | POV_TOT | HSG_VAL | POLYID | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 06061022001 | Sacramento | 5501 | 1077 | 518 | 4961 | 29 | 82 | 336 | 31 | ... | 1187 | 117 | 663.0 | 42 | 52941 | 5461 | 470 | 225900 | 1 | POLYGON ((740409.853 4338451.728, 740199.864 4... |
| 1 | 06061020106 | Sacramento | 2072 | 396 | 109 | 1603 | 0 | 28 | 391 | 41 | ... | 522 | 38 | 229.0 | 19 | 51958 | 2052 | 160 | 249300 | 2 | POLYGON ((753400.378 4347151.08, 753395.816 43... |
| 2 | 06061020107 | Sacramento | 3633 | 911 | 126 | 1624 | 9 | 0 | 1918 | 41 | ... | 698 | 86 | 197.0 | 0 | 32992 | 3604 | 668 | 175900 | 3 | POLYGON ((758318.262 4352123.456, 758319.774 4... |
| 3 | 06061020105 | Sacramento | 1683 | 281 | 154 | 1564 | 0 | 55 | 60 | 4 | ... | 519 | 5 | 256.0 | 6 | 54556 | 1683 | 116 | 302300 | 4 | POLYGON ((750839.595 4342678.807, 750805.84 43... |
| 4 | 06061020200 | Sacramento | 5794 | 1278 | 830 | 5185 | 17 | 13 | 251 | 229 | ... | 1260 | 155 | 506.0 | 59 | 50815 | 5771 | 342 | 167300 | 5 | POLYGON ((670062.02 4311030.409, 670133.819 43... |
5 rows × 31 columns
sacramento.plot('BLACK')
<Axes: >
Aspatial Segregation Indices¶
To compute an aspatial segregation index, pass a dataframe, a group population variable, and total population variable to the index’s class
from segregation.singlegroup import Dissim
dissim = Dissim(sacramento, group_pop_var='BLACK',
total_pop_var='TOT_POP')
The statistic attribute holds the value of the segregation index, and the data attribute holds the data used to calculate the index
dissim.statistic
np.float64(0.4883394024705785)
dissim.data.head()
| BLACK | TOT_POP | geometry | |
|---|---|---|---|
| 0 | 29 | 5501 | POLYGON ((740409.853 4338451.728, 740199.864 4... |
| 1 | 0 | 2072 | POLYGON ((753400.378 4347151.08, 753395.816 43... |
| 2 | 9 | 3633 | POLYGON ((758318.262 4352123.456, 758319.774 4... |
| 3 | 0 | 1683 | POLYGON ((750839.595 4342678.807, 750805.84 43... |
| 4 | 17 | 5794 | POLYGON ((670062.02 4311030.409, 670133.819 43... |
Spatial Segregation Indices¶
For calculating spatial segregation indices, the package implements two classes of indices: spatially-explicit and spatially-implicit.
Spatially-explicit indices are those for which space was a formal consideration in the index’s original formulation, whereas spatially-implicit indices are developed using the logic of Reardon and O’Sulivan.
For the latter,(otherwise called generalized spatial segregation indices) the package can incorporate spatial relationships represented by either a libpysal.W weights object or a pandana.Network network object, which means generalized spatial segregation indices can be computed according to many different spatial relationships which could include contiguity, distance, or network connectivity. This flexibility is particularly useful for specifying appropriate “neighborhood” definitions for different types of input data (which could be, e.g. housing units, census tracts, or counties)
For spatially-explicit indices, they can be called like any other, though some may have additional arguments:
from segregation.singlegroup import AbsoluteCentralization, Gini
cent = AbsoluteCentralization(sacramento, group_pop_var='BLACK',
total_pop_var='TOT_POP')
cent.statistic
np.float64(0.8491771822066596)
Euclidian distance based measures¶
For generalized spatial indices, a distance parameter can be passed to the index of choice. Under the hood, the input data will be passed through a kernel function with the distance parameter as the kernel bandwidth.
(note in this case because the CRS of the sacramento dataframe is UTM, the units are in meters)
# aspatial gini index
aspatial_gini = Gini(sacramento, group_pop_var='BLACK',
total_pop_var='TOT_POP')
# generalized spatial gini index
gen_spatialgini = Gini(sacramento, group_pop_var='BLACK',
total_pop_var='TOT_POP', distance=2000)
gen_spatialgini.statistic
0.5368015908262396
aspatial_gini.statistic
0.6361755332635235
Examining the data attribute of the fitted index shows how the input data are transformed
# kernelized data
gen_spatialgini.data.plot('BLACK')
<Axes: >
# original data
sacramento.plot('BLACK')
<Axes: >
Network distance based measures¶
Instead of a euclidian distance-based kernel, each generalized spatial segregation index can be calculated using accssibility analysis on a transportation network instead. Since people can’t fly, using a travel network to measure spatial distances is more conceptually pure to the spirit of segregation indices
Note: the network-distance workflow below relies on the optional
pandarmpackage and a pre-built network file, so those cells are taggedskip-executionand are not run during automated testing.
import pandana as pdna
A network can be created using the urbanaccess package, or the built-in get_osm_network function from the segregation.util module. Alternatively, metropolitan-scale networks from OpenStreetMap are also available in the CGS quilt bucket (named by CBSA FIPS code)
net = pdna.Network.from_hdf5('../40900.h5')
network_spatialgini = Gini(sacramento, group_pop_var='BLACK',
total_pop_var='TOT_POP', distance=2000,
network=net, decay='linear')
Comparing spatial gini indices based on straight-line distance versus network distance:
network_spatialgini.statistic
0.5848616778202473
gen_spatialgini.statistic
0.5368015908262396
The segregation statistic using network distance to construct neighborhoods is higher than using the one using unrestricted euclidian distance
Batch-Computing Single-Group Measures¶
To compute all single group indices in one go, the package provides a wrapper function in the batch module
from segregation.batch import batch_compute_singlegroup
all_singlegroup = batch_compute_singlegroup(sacramento, group_pop_var='BLACK', total_pop_var='TOT_POP')
all_singlegroup
| Statistic | |
|---|---|
| Name | |
| AbsoluteCentralization | 0.8492 |
| AbsoluteClustering | 0.0610 |
| AbsoluteConcentration | 0.9814 |
| Atkinson | 0.3659 |
| BiasCorrectedDissim | 0.4878 |
| BoundarySpatialDissim | 0.4501 |
| ConProf | 0.1128 |
| CorrelationR | 0.1010 |
| Delta | 0.9073 |
| DensityCorrectedDissim | 0.3352 |
| Dissim | 0.4883 |
| DistanceDecayInteraction | 0.8524 |
| DistanceDecayIsolation | 0.1233 |
| Entropy | 0.1815 |
| Gini | 0.6362 |
| HutchensSqrt | 0.2037 |
| Interaction | 0.8379 |
| Isolation | 0.1621 |
| MinMax | 0.6562 |
| ModifiedDissim | 0.4762 |
| ModifiedGini | 0.6239 |
| PARDissim | 0.4818 |
| RelativeCentralization | 0.0769 |
| RelativeClustering | 1.6101 |
| RelativeConcentration | 0.7788 |
| SpatialDissim | 0.4463 |
| SpatialProxProf | 0.1160 |
| SpatialProximity | 1.0552 |