Multiscalar Segregation Profiles¶
%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
For measuring spatial segregation dynamics, the segregation package provides a function for measuring multiscalar segregation profiles, as introduced by Reardon et al.
The multiscalar profile is a tool for measuring spatial segregation dynamics–the way that a segregation index changes values as the concept of a neighborhood changes, and what that tells us about macro versus micro patterns of segregation.
The basic idea is to calculate a segregation statistic, then expand the spatial scope of a neighborhood, recalculate the statistic, and repeat.
A multiscalar profile can be computed for any generalized spatial segregation index, which in the case of the segregation package, means a total of 23 indices, including single and multigroup varieties
from segregation.batch import implicit_multi_indices, implicit_single_indices
len(implicit_single_indices) + len(implicit_multi_indices)
24
Computing a Single Group Profile¶
import geopandas as gpd
import matplotlib.pyplot as plt
from libpysal.examples import load_example
from segregation.singlegroup import Dissim, Gini
from segregation.dynamics import compute_multiscalar_profile
sacramento = gpd.read_file(load_example("Sacramento1").get_path("sacramentot2.shp"))
sacramento = sacramento.to_crs(sacramento.estimate_utm_crs())
sac_gini_profile = compute_multiscalar_profile(sacramento, segregation_index=Gini,
group_pop_var="BLACK", total_pop_var="TOT_POP",
distances= range(500,5500,500))
The function returns a pandas Series whose index is the neighborhood distance threshold, and the value is the segregation statistic.
sac_gini_profile
distance
0 0.636176
500 0.636060
1000 0.623794
1500 0.585519
2000 0.536802
2500 0.499355
3000 0.472811
3500 0.452414
4000 0.436664
4500 0.424351
5000 0.412981
Name: Gini, dtype: float64
As such, the profile is easy to plot:
sac_gini_profile.plot()
<Axes: xlabel='distance'>
A good way to compare multiscalar profiles is to plot them in the same figure. For example to compare profiles for gini and dissimilarity indices:
sac_dissim_profile = compute_multiscalar_profile(sacramento, segregation_index=Dissim,
group_pop_var="BLACK", total_pop_var="TOT_POP",
distances= range(500,5500,500))
from libpysal.weights import DistanceBand
fig, ax = plt.subplots(figsize=(8,8))
sac_dissim_profile.plot(ax=ax)
sac_gini_profile.plot(ax=ax)
ax.legend()
<matplotlib.legend.Legend at 0x7f6bcfd95fd0>
The multiscalar profiles for Gini and Dissimilarity indices are very similar, but have slightly different shapes.
Network versus Euclidian Multiscalar Profiles¶
To calculate a multiscalar profile using travel network distance instead of Euclidian distance, simply pass a pandana.Network object to the function
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
net = pdna.Network.from_hdf5("../40900.h5")
net_dissim_profile = compute_multiscalar_profile(sacramento, segregation_index=Dissim,
group_pop_var="BLACK", total_pop_var="TOT_POP",
network = net,
distances= range(500,5500,500))
fig, ax = plt.subplots(figsize=(8,8))
sac_dissim_profile.name='Dissim'
net_dissim_profile.name='Network Dissim'
sac_dissim_profile.plot(ax=ax)
net_dissim_profile.plot(ax=ax)
ax.legend()
In this case, comparing the two profiles reveals the role of travel infrastructure on the experience and measurement of segregation; the network-based dissimilarity profile falls slower, indicating that travel networks help insulate segregation at larger distances
Computing a Multi Group Profile¶
To calculate a multigroup index (e.g. the multigroup information theory index from the original paper), simply pass a MultiGroupIndex class to the function with multigroup arguments instead of singlegroup
from segregation.multigroup import MultiInfoTheory, MultiGini
multi_info_profile = compute_multiscalar_profile(sacramento, segregation_index=MultiInfoTheory,
groups=["HISP", 'BLACK', "WHITE"], distances=range(500,5000,500))
multi_gini_profile = compute_multiscalar_profile(sacramento, segregation_index=MultiGini,
groups=["HISP", 'BLACK', "WHITE"], distances=range(500,5000,500))
fig, ax = plt.subplots(figsize=(8,8))
multi_gini_profile.plot(ax=ax)
multi_info_profile.plot(ax=ax)
ax.legend()
<matplotlib.legend.Legend at 0x7f6bcfd9fb60>
Batch-Computing Profiles¶
from segregation.batch import batch_multiscalar_singlegroup, batch_multiscalar_multigroup
single_profs = batch_multiscalar_singlegroup(sacramento,group_pop_var="BLACK", total_pop_var="TOT_POP",
distances= range(500,5500,500))
multi_profs = batch_multiscalar_multigroup(sacramento, distances=range(500,5000,500), groups=["HISP", 'BLACK', "WHITE"])
With several profiles to examine at once, it’s helpful to use an interactive plotting library like hvplot
Note:
hvplotis an optional dependency used only for interactive plotting; the cells below are taggedskip-executionand are not run during automated testing.
import hvplot.pandas
single_profs.hvplot(width=850, height=450)
multi_profs.hvplot(width=850, height=550)