17  Space, Scale & Dynamics

Code
import hvplot.pandas

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import contextily as ctx

from geosnap import DataStore
from geosnap import io as gio
from geosnap.analyze import segdyn
from geosnap.io import get_network_from_gdf
from geosnap.visualize import animate_timeseries, plot_timeseries
from IPython.display import Image
from libpysal import weights
from libpysal.graph import Graph
from segregation import singlegroup, multigroup, batch
from segregation.dynamics import compute_multiscalar_profile

%load_ext watermark
%watermark -iv -a "author: eli knaap"
OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.
Author: author: eli knaap

geopandas  : 1.0.1
pandas     : 2.2.3
libpysal   : 4.12.1
segregation: 2.5.3.dev0+g3b3ee00.d20250425
IPython    : 8.31.0
matplotlib : 3.10.0
geosnap    : 0.15.3.dev3+g3fa22c0.d20250409
contextily : 1.6.2
hvplot     : 0.11.2

The distinction of considering multigroup segregation instead of dichotomous segregation is profound; it involves including new variables in the functions (one for each additional racial group) or adding new columns to the data matrix being reduced. However, the decision to include or to exclude other variables such as neighborhood contiguity, tract area, or proximity to the central city is as fundamental to the understanding of segregation data as is the choice of whether or not to restrict the scenario to a majority race and a single minority race or to allow for a multiple-race scenario.

Grannis (2002) p. 70

17.1 Spatial Segregation Indices

Every index in the segregation package can leverage spatial relationships in its computation. Some segregation indices include a spatially-explicit formulation, for example the perimeter-area-ratio measure proposed by Wong (1993) or the interaction indices of Morgan (1983) and Morril (1991), each of which provide ways to modify specific indices (dissimilarity in the first and Isolation/Exposure in the latter two) using particular forms of spatial structure (contiguity-based weights in the and distance-decay weights in the latter).

More recently, Reardon & O’Sullivan (2004) provide a way to generalize any (non-spatial) segregation index by an arbitrary spatial weights matrix, which modifies the input units. In their original paper, Reardon and O’Sullivan use a kernel-based \(W\) based on Euclidean distances between observations (similar to Morril), though their approach can be adapted to any weight structure, including those based on street network connectivity, which adopt the notion of “egohoods” (shown previously in Chapter 11) (Hipp & Boessen, 2013; Kim & Hipp, 2019; Knaap & Rey, 2023; Roberto, 2018). In this example, we will look at two iconic metropolitan regions in Tennessee, Memphis and Knoxville, focusing on segregation of the non-Hispanic Black population, whose “hypersegregation” has been a long focus of social science and civil rights inquiry for understanding broader patterns of urban inequality (Eitle, 2009; Hess et al., 2019; Massey, 2020; Massey & Denton, 1989; Massey & Tannen, 2015).

Code
datasets = DataStore()

mem = gio.get_acs(DataStore(), msa_fips="32820", years=2019)
mem = mem.to_crs(mem.estimate_utm_crs())

knox = gio.get_acs(DataStore(), msa_fips="28940", years=2019)
knox = knox.to_crs(knox.estimate_utm_crs())

f, ax = plt.subplots(1, 2, figsize=(8, 5))

knox.plot("p_nonhisp_black_persons", scheme="fisher_jenks", ax=ax[0], alpha=0.6)
ctx.add_basemap(ax=ax[0], source=ctx.providers.CartoDB.Positron, crs=knox.crs)
ax[0].set_title("Knoxville")

mem.plot("p_nonhisp_black_persons", scheme="fisher_jenks", ax=ax[1], alpha=0.6)
ctx.add_basemap(ax=ax[1], source=ctx.providers.CartoDB.Positron, crs=mem.crs)
ax[1].set_title("Memphis")

for ax in ax:
    ax.axis("off")
plt.tight_layout()

Which of these places looks more segregated? From the maps alone, the prediction is challenging for a few different reasons. First, the heterogenous size and shape of units both within and across metro regions can make comparisons difficult, and this is compounded by the fact that they each use their own relative classification scheme. In each frame we have a reasonable sense of the relative population distribution, but the colors are not comparable across panels. Perhaps more importantly, the regions have very different demographic makeups.

Code
print(
    f"Knoxville % Black non-Hispanic/Latino: {(knox.n_nonhisp_black_persons.sum() / knox.n_total_pop.sum()).round(3)}"
)
print(
    f"Memphis % Black non-Hispanic/Latino: {(mem.n_nonhisp_black_persons.sum() / mem.n_total_pop.sum()).round(3)}"
)
Knoxville % Black non-Hispanic/Latino: 0.058
Memphis % Black non-Hispanic/Latino: 0.469
Code
print(
    f"Knoxville Entropy: {round(singlegroup.Entropy(knox, group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",).statistic, 3)}"
)
print(
    f"Memphis Entropy: {round(singlegroup.Entropy(mem, group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",).statistic, 3)}"
)
Knoxville Entropy: 0.335
Memphis Entropy: 0.394

17.1.1 Single Group

Note

To define the neighborhood around each observation, the segregation package currently has a clunky interface that allows users to provide either a libpysal.W or a pandana.Network object, each of which have different distance-decay parameters. In the [near] future, the package will be updated to accept only a libpysal.Graph object in place of the W, and the network-based and Euclidean measures will share a common kernel interface.

Using Reardon and O’Sullivan’s technique, the segregation package allows users to parameterize space into a conventional segregation measure in a few different ways. One option is to pass a spatial weights matrix directly to the w argument in any segregation index class. This provides the ultimate flexibility because you can create the W (or, at the moment use a Graph.to_W()) explicitly using any convention you like. In theory, you could use something like a Queen or Rook graph, but these these don’t have a strong conceptual foundation since tract/blockgroup contiguity is a weaker way to proxy social interaction, especially given the heterogenous size and shape of most administrative geographies. Thus, as a shortcut, you can instead pass a distance argument, and the name of a kernel decay function which will create the necessary weights matrix internally.

Code
singlegroup.Entropy(
    mem,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distance=2000,
).statistic
0.3261183985611953

The default options are to use Euclidean distance with a linear decay (triangular kernel). These same options can be passed straight to the batch_compute functions. Here we create two versions of each index, a classic aspatial version and a spatial version based on a two-kilometer simple distance-decay measure.

Code
aspatial = batch.batch_compute_singlegroup(
    knox, group_pop_var="n_nonhisp_black_persons", total_pop_var="n_total_pop"
)
spatial = batch.batch_compute_singlegroup(
    knox,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distance=2000,
)

names = ["Entropy", "Isolation"]
indices = pd.concat([aspatial.loc[names], spatial.loc[names]], axis=1)
cols = ["aspatial", "spatial 2km"]
indices.columns = cols
indices
aspatial spatial 2km
Name
Entropy 0.335 0.2658
Isolation 0.289 0.2748

In the Knoxville metro, the entropy index is larger (more segregation) for the aspatial index than the two-kilometer index, showing that when you increase the scope of the neighborhood (to 2km), evenness increases and the population inside the neighborhood becomes closer on average to the regional population distribution. For the isolation index in Knoxville, however, the measure actually increases slightly for the spatialized index. That means as the neighborhood as expanded in Knoxville, within-group interaction increases. This reflects the clustering shown in the map where the non-Hispanic Black population is mainly clustered into a single portion of the city of Knoxville, rather than spread the most of the region.

17.1.2 Multi Group

Code
pop_groups = [
    "n_asian_persons",
    "n_hispanic_persons",
    "n_nonhisp_black_persons",
    "n_nonhisp_white_persons",
]

aspatial = batch.batch_compute_multigroup(knox, groups=pop_groups)
spatial = batch.batch_compute_multigroup(
    knox,
    groups=pop_groups,
    distance=2000,
)
names = ["MultiInfoTheory", "MultiNormExposure"]
indices = pd.concat([aspatial.loc[names], spatial.loc[names]], axis=1)
indices.columns = cols
indices
aspatial spatial 2km
Name
MultiInfoTheory 0.2714 0.2042
MultiNormExposure 0.1897 0.1603

17.1.3 Network Distance

In Chapter 10, we saw the importance of considering street network contiguity when creating realistic measures of distance in urban environments, which is a concern echoed many times in the segregation literature (Knaap & Rey, 2023; Roberto, 2018). Toward that end, it is trivial to incorporate network distance into any spatial segregation measure by passing a pandana.Network object that covers the same study area (and whose nodes are stored in the same coordinate system). Here we can compare measures based on simple Euclidean distance versus distance using shortest network paths between observations.

Code
knox_net = get_network_from_gdf(knox)
g_net = Graph.build_travel_cost(
    df=knox.set_geometry(knox.centroid), network=knox_net, threshold=2000
)
g_dist = Graph.build_distance_band(knox.set_geometry(knox.centroid), threshold=2000)
g_dist.explore(knox)
/Users/knaaptime/Dropbox/projects/geosnap/geosnap/io/networkio.py:71: UserWarning: GeoDataFrame is stored in coordinate system EPSG:32616 so the pandana.Network will also be stored in this system
  warn(
Generating contraction hierarchies with 16 threads.
Setting CH node vector of size 139201
Setting CH edge vector of size 353402
Range graph removed 364326 edges of 706804
. 10% . 20% . 30% . 40% . 50% . 60% . 70% . 80% . 90% . 100%
/Users/knaaptime/miniforge3/envs/urban_analysis/lib/python3.12/site-packages/libpysal/graph/_utils.py:125: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  adjtable_filled = pd.concat(
Make this Notebook Trusted to load map: File -> Trust Notebook
Code
f, ax = plt.subplots(1, 2, figsize=(8, 4.5))

g_dist.plot(knox, ax=ax[0], nodes=False)
g_net.plot(knox, ax=ax[1], nodes=False)

ax[0].set_title("Euclidean Distance")
ax[1].set_title("Network Distance")

for ax in ax:
    ax.set_ylim([3.97e6, 3.995e6])
    ax.set_xlim([758000,785000])
    ctx.add_basemap(ax=ax, source=ctx.providers.CartoDB.Positron, crs=knox.crs)
    ax.axis("off")
plt.tight_layout()

Like in Chapter 7, the network-based graph provides less connectivity within the same two-kilometer distance threshold because traversing the network requires twists and turns rather than allowing a direct line to the chosen location. These same issues have implications for segregation measures; in this case we will compare an Entropy-based measure using Euclidean and network distance below.

Code
i_euc = singlegroup.Entropy(
    knox,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distance=2000,
)
i_net = singlegroup.Entropy(
    knox,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distance=2000,
    network=knox_net,
    decay="linear",
)

print(f"Euclidean-Distance: {round(i_euc.statistic,3)}")
print(f"Network-Distance: {round(i_net.statistic, 3)}")
Euclidean-Distance: 0.266
Network-Distance: 0.33

As expected, the segregation measure is higher (more segregation) when accounting for network connectivity rather than using simple Euclidean approximation (quite a bit higher, actually). In the next chapter, we explore methods for assessing the statistical significance of this difference.

17.2 The Multiscalar Profile

The multiscalar segregation profile introduced by Reardon et al. (2008) and applied by Lee et al. (2008) is a way of measuring how global versus local the segregation patterns are in a region. It is a way of measuring (and visualizing) the way a segregation measure changes over different notions of spatial scale, and thus captures a certain kind of spatial dynamic. As stylized examples, consider a city where one population groups lives on the eastern half and another group lives on the western half (large-scale/macro segregation) versus a city full of dense apartment buildings, but each building is occupied exclusively by members of a single population group

White (1983) termed this the “checkerboard problem.” If one allows the squares on a checkerboard to represent neighborhoods, once the composition of each square is given, any spatial rearrangement of them will result in the same calculation for most segregation indices. Thus, “A city in which all the nonwhite parcels were concentrated into one single ghetto would have the same calculated segregation as a city with dispersed pockets of minority residents” White 1983, pp. 1010–11.

Grannis (2002) p. 77

Reardon et al. (2008) visually describe the micro/macro segregation phenomenon using this figure

To compute a segregation profile, we calculate a series of segregation measures with an increasingly large distance threshold to define the local neighborhood of each unit. Conceptually, this means the spatial Graph used to define the neighborhood is becoming increasingly interconnected (recall the increasing distance band graphs shown in Figure 7.1). Thus, to compute a profile using the segregation package, we pass a dataframe, the class of the desired index, the appropriate arguments (e.g. population group names), and a set of distances that define the profile. Here we will look at increments of 500 meters from 500 to 5000.

Code
knox[pop_groups].sum() / knox['n_total_pop'].sum()
n_asian_persons            0.015835
n_hispanic_persons         0.038723
n_nonhisp_black_persons    0.057604
n_nonhisp_white_persons    0.864020
dtype: float64
Code
distances = list(range(500, 5500, 500))

# entropy profiles
mprof = compute_multiscalar_profile(
    mem,
    segregation_index=singlegroup.Entropy,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distances=distances,
)
kprof = compute_multiscalar_profile(
    knox,
    segregation_index=singlegroup.Entropy,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distances=distances,
)

# isolation profiles
mprof_iso = compute_multiscalar_profile(
    mem,
    segregation_index=singlegroup.Isolation,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distances=distances,
)
kprof_iso = compute_multiscalar_profile(
    knox,
    segregation_index=singlegroup.Isolation,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="n_total_pop",
    distances=distances,
)

The profile function returns a pandas series of segregation measures, indexed by the distance used to compute the measure.

Code
mprof
distance
0       0.394493
500     0.394184
1000    0.386338
1500    0.357810
2000    0.326118
2500    0.297081
3000    0.269000
3500    0.243039
4000    0.220261
4500    0.200588
5000    0.183262
Name: Entropy, dtype: float64

A quick glance at the series shows how the information theory index falls as spatial scale increases. This format also makes it trivial to plot the profile or compute the “macro/micro segregation ratio”, which Reardon et al. (2008) define as \(H_{4000m} / H_{500m}\).

Code
mprof.loc[4000] / mprof.loc[500]
0.5587768964386302

This number indicates that a little more than half of the segregation in Knoxville at the 500m scale is explained by segregation at the 4km scale, which is a relatively small number. In this case, the ratio shows that the Knoxville metro is characterized primarily by small-scale (micro) segregation. We can also look at how the segregation profiles differ by region. If we plot them all on the same graph, we can compare the slopes of the lines to see how the shape of segregation differs between the two Tennessee metropolitan regions.

The slope of the segregation profile requires interpretation as well. Suppose segregation levels were the same when measured using either the 500m- or 4,000m-radius environments… Such uniformity implies that all people in a metropolitan area live in places where racial composition does not vary appreciably over distances shorter than several kilometers. So a “flat” segregation profile corresponds to a metropolitan area where the geographic scale of segregation is large—where a large portion of micro-segregation is attributable to macro-segregation patterns—while a “steep” profile corresponds to an area where much of the variation in racial composition occurs over distances shorter than 4,000m.

Reardon et al. (2008), p.503

Code
f, ax = plt.subplots(1, 2, figsize=(8, 4))

mprof.rename("Memphis").plot(color="blue", legend=True, ax=ax[0])
kprof.rename("Knoxville").plot(color="red", legend=True, ax=ax[0])
ax[0].set_title("Entropy Profiles")

mprof_iso.rename("Memphis").plot(color="blue", legend=True, ax=ax[1])
kprof_iso.rename("Knoxville").plot(color="red", legend=True, ax=ax[1])
ax[1].set_title("Isolation Profiles")
plt.suptitle('non-Hispanic Black Segregation Profiles')
plt.tight_layout()

Multigroup indices work similarly to single group indices, with the appropriate arguments.

Code
# entropy profiles
mprof = compute_multiscalar_profile(
    mem,
    segregation_index=multigroup.MultiInfoTheory,
    groups=pop_groups,
    distances=distances,
)
kprof = compute_multiscalar_profile(
    knox,
    segregation_index=multigroup.MultiInfoTheory,
    groups=pop_groups,
    distances=distances,
)

# isolation profiles
mprof_iso = compute_multiscalar_profile(
    mem,
    segregation_index=multigroup.MultiNormExposure,
    groups=pop_groups,
    distances=distances,
)
kprof_iso = compute_multiscalar_profile(
    knox,
    segregation_index=multigroup.MultiNormExposure,
    groups=pop_groups,
    distances=distances,
)

# plot
f, ax = plt.subplots(1, 2, figsize=(8, 4))

mprof.rename("Memphis").plot(color="blue", legend=True, ax=ax[0])
kprof.rename("Knoxville").plot(color="red", legend=True, ax=ax[0])
ax[0].set_title("Information Theory Profiles")

mprof_iso.rename("Memphis").plot(color="blue", legend=True, ax=ax[1])
kprof_iso.rename("Knoxville").plot(color="red", legend=True, ax=ax[1])
ax[1].set_title("Exposure Profiles")
plt.suptitle("Multigroup Segregation Profiles")
plt.tight_layout()

Here we see segregation is higher in Memphis at every scale, but the two profiles have distinctly different shapes, with Knoxville remaining flatter at small scales while Memphis has a steeper slope in the 1-2km range.

And similar to the computation of any individual index, you can compute multiscalar profiles using either Euclidean or Network distance. To compare profiles in Knoxville, we need only pass the Network object to the batch computation function, then we can plot both profiles on the same graph again to see where they diverge.

Code
kprof_network = compute_multiscalar_profile(
    knox,
    segregation_index=multigroup.MultiInfoTheory,
    groups=pop_groups,
    distances=distances,
    network=knox_net,
    decay="linear",
)

kprof.rename("Knoxville Euclidean").plot(color="blue", legend=True)
kprof_network.rename("Knoxville Network").plot(color="red", legend=True, figsize=(5,3))

At every spatial scale, segregation is higher when measured using network-based distance rather than pure Euclidean distance. But the pattern is also more pronounced at smaller scales, where it is clear the network-based profile stays flatter through the two kilometer range, whereas the Euclidean profile declines over that range. This result highlights that in Knoxville, the travel network is particularly isolating in small neighborhood scales.

17.3 Change over Time

One common inquiry is to examine how segregation has changed over time in some particular place or collection of places (Acs et al., 2017; Bailey, 2012; Iceland et al., 2002; Intrator et al., 2016; Reardon et al., 2018; Timberlake & Iceland, 2007). To make this simpler for applied research, the geosnap package provides functions that efficiently operate on long-form geodatataframes to return a series of segregation measures computed for each time period. Below we will return to the Washington D.C. region for an example. Note this is just a simple example for demonstration purposes; we will create a “time-series” of ACS data using a set of overlapping 5-year survey estimates. I use time-series in quotes because this is effectively a comparison of overlapping rolling averages, so while we can look at trends we can make valid cross sectional comparisons against two periods unless the 5-year sample is non-overlapping.

Code
dc = gio.get_acs(
    datasets, msa_fips="47900", years=list(range(2012, 2020)), constant_dollars=False
)
dc21 = gio.get_acs(
    datasets, msa_fips="47900", years=[2020, 2021], constant_dollars=False
)
dc21 = dc21.set_crs(dc.crs)
dc = gpd.GeoDataFrame(pd.concat([dc, dc21]))
dc = dc.to_crs(dc.estimate_utm_crs())

animate_timeseries(
    dc,
    "p_nonhisp_black_persons",
    scheme="fisherjenks",
    cmap="Blues",
    filename="dc_black_pop_change.gif",
    fps=1.5,
    figsize=(9,10)
)
/Users/knaaptime/Dropbox/projects/geosnap/geosnap/io/constructors.py:190: UserWarning: `constant_dollars` is True, but no `currency_year` was specified. Resorting to max value of 2019
  warn(
/Users/knaaptime/Dropbox/projects/geosnap/geosnap/io/constructors.py:190: UserWarning: `constant_dollars` is True, but no `currency_year` was specified. Resorting to max value of 2021
  warn(
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 864x960 with 0 Axes>
<Figure size 960x960 with 0 Axes>

17.3.1 Single-Group Indices

To generate a range of indices for a long-form dataframe, geosnap provides the singlegroup_tempdyn function which batch computes segregation indices for each unique time period in the dataframe. Here we will look at non-Hispanic Black segregation in the D.C. region using each 5-year ACS sampling period between 2008-2012 and 2017-2021.

Code
dc["blackwhite"] = dc.n_nonhisp_black_persons + dc.n_nonhisp_white_persons
segs_single = segdyn.singlegroup_tempdyn(
    dc, group_pop_var="n_nonhisp_black_persons", total_pop_var="blackwhite"
)
segs_single
  0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]  0%|          | 0/27 [00:00<?, ?it/s]AbsoluteCentralization:   0%|          | 0/27 [00:00<?, ?it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 57.18it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 56.61it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 55.65it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 54.65it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 55.34it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 55.83it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 54.48it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 54.08it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 52.90it/s]AbsoluteClustering:   4%|▎         | 1/27 [00:00<00:00, 52.23it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  7.10it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  7.10it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  7.09it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  7.09it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  7.10it/s]             Atkinson:  11%|█         | 3/27 [00:00<00:03,  7.09it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  7.10it/s]BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  7.09it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.86it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.86it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.86it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.86it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.66it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.66it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.66it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.66it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.41it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.41it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.38it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.38it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.37it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.37it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:03,  6.36it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:03,  6.36it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.41it/s]             Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.38it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.41it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.36it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.38it/s]Atkinson:  11%|█         | 3/27 [00:00<00:03,  6.37it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.36it/s]BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:03,  6.37it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:04,  5.62it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:04,  5.62it/s]AbsoluteClustering:   7%|▋         | 2/27 [00:00<00:04,  5.59it/s]AbsoluteConcentration:   7%|▋         | 2/27 [00:00<00:04,  5.59it/s]Atkinson:  11%|█         | 3/27 [00:00<00:04,  5.62it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:04,  5.62it/s]Atkinson:  11%|█         | 3/27 [00:00<00:04,  5.59it/s]             BiasCorrectedDissim:  15%|█▍        | 4/27 [00:00<00:04,  5.59it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  5.00it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  5.00it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.94it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.94it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.95it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.95it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.92it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.92it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.90it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.90it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.86it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.86it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.88it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:00<00:04,  4.88it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:01<00:04,  4.86it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:01<00:04,  4.86it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:01<00:05,  4.37it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:01<00:05,  4.37it/s]BiasCorrectedDissim:  19%|█▊        | 5/27 [00:01<00:05,  4.34it/s]BoundarySpatialDissim:  19%|█▊        | 5/27 [00:01<00:05,  4.34it/s]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]              BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:24,  1.21s/it]Delta:  30%|██▉       | 8/27 [00:05<00:22,  1.21s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:21,  1.21s/it]CorrelationR:  26%|██▌       | 7/27 [00:05<00:24,  1.21s/it]Delta:  30%|██▉       | 8/27 [00:05<00:22,  1.21s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:21,  1.21s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]              BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:24,  1.21s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:25,  1.21s/it]              Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.21s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:21,  1.21s/it]CorrelationR:  26%|██▌       | 7/27 [00:05<00:24,  1.21s/it]Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.21s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:21,  1.21s/it]CorrelationR:  26%|██▌       | 7/27 [00:05<00:24,  1.21s/it]Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.21s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:21,  1.21s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:26,  1.25s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:26,  1.25s/it]              BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:26,  1.25s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:26,  1.25s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:25,  1.25s/it]Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.25s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:22,  1.25s/it]CorrelationR:  26%|██▌       | 7/27 [00:05<00:25,  1.25s/it]Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.25s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:22,  1.25s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:26,  1.26s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:26,  1.26s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:25,  1.26s/it]Delta:  30%|██▉       | 8/27 [00:05<00:23,  1.26s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:22,  1.26s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:27,  1.30s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:27,  1.30s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:26,  1.30s/it]Delta:  30%|██▉       | 8/27 [00:05<00:24,  1.30s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:23,  1.30s/it]BoundarySpatialDissim:  22%|██▏       | 6/27 [00:05<00:27,  1.31s/it]ConProf:  22%|██▏       | 6/27 [00:05<00:27,  1.31s/it]              CorrelationR:  26%|██▌       | 7/27 [00:05<00:26,  1.31s/it]Delta:  30%|██▉       | 8/27 [00:05<00:24,  1.31s/it]       DensityCorrectedDissim:  33%|███▎      | 9/27 [00:05<00:23,  1.31s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:40,  2.38s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:40,  2.38s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.38s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:40,  2.38s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:40,  2.38s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.38s/it]DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:25,  1.70s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:25,  1.70s/it]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:25,  1.71s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:25,  1.71s/it]  DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:40,  2.41s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:40,  2.41s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.41s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:41,  2.42s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:41,  2.42s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.42s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:41,  2.42s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:41,  2.42s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.42s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:41,  2.43s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:41,  2.43s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.43s/it]DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:25,  1.73s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:25,  1.73s/it]  DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.45s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.45s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:18,  1.45s/it]   DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:41,  2.43s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:41,  2.43s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.43s/it]DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.45s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.45s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:18,  1.45s/it]   DensityCorrectedDissim:  37%|███▋      | 10/27 [00:18<00:41,  2.44s/it]Dissim:  37%|███▋      | 10/27 [00:18<00:41,  2.44s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:18<00:38,  2.44s/it]DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:26,  1.74s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:26,  1.74s/it]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:26,  1.74s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:26,  1.74s/it]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]  DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.47s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.47s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:19,  1.47s/it]   DistanceDecayInteraction:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:18<00:26,  1.75s/it]  DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:19,  1.48s/it]   DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:19,  1.48s/it]   DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.48s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:19,  1.48s/it]   DistanceDecayIsolation:  48%|████▊     | 13/27 [00:18<00:20,  1.49s/it]Entropy:  48%|████▊     | 13/27 [00:18<00:20,  1.49s/it]               Gini:  52%|█████▏    | 14/27 [00:18<00:19,  1.49s/it]   DistanceDecayIsolation:  48%|████▊     | 13/27 [00:19<00:20,  1.49s/it]Entropy:  48%|████▊     | 13/27 [00:19<00:20,  1.49s/it]               Gini:  52%|█████▏    | 14/27 [00:19<00:19,  1.49s/it]   Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.28s/it]  Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.28s/it]  MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.28s/it]   MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.28s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.28s/it]ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.28s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.29s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.29s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.29s/it]  MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.29s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.29s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.28s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.28s/it]  Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.28s/it]  MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.28s/it]   MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.28s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.28s/it]ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.28s/it]ModifiedDissim:  70%|███████   | 19/27 [00:20<00:05,  1.44it/s]ModifiedGini:  70%|███████   | 19/27 [00:20<00:05,  1.44it/s]  ModifiedDissim:  70%|███████   | 19/27 [00:20<00:05,  1.44it/s]ModifiedGini:  70%|███████   | 19/27 [00:20<00:05,  1.44it/s]  Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.30s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.30s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.30s/it]  MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.30s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.30s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.29s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.29s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.29s/it]  DensityCorrectedDissim:  37%|███▋      | 10/27 [00:20<00:46,  2.74s/it]Dissim:  37%|███▋      | 10/27 [00:20<00:46,  2.74s/it]                MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.29s/it]   DistanceDecayInteraction:  41%|████      | 11/27 [00:20<00:43,  2.74s/it]ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.29s/it]Gini:  56%|█████▌    | 15/27 [00:20<00:15,  1.30s/it]Interaction:  56%|█████▌    | 15/27 [00:20<00:15,  1.30s/it]Isolation:  59%|█████▉    | 16/27 [00:20<00:14,  1.30s/it]  MinMax:  63%|██████▎   | 17/27 [00:20<00:12,  1.30s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:20<00:11,  1.30s/it]DensityCorrectedDissim:  37%|███▋      | 10/27 [00:20<00:46,  2.75s/it]Dissim:  37%|███▋      | 10/27 [00:20<00:46,  2.75s/it]                DistanceDecayInteraction:  41%|████      | 11/27 [00:20<00:44,  2.75s/it]ModifiedDissim:  70%|███████   | 19/27 [00:20<00:05,  1.43it/s]ModifiedGini:  70%|███████   | 19/27 [00:20<00:05,  1.43it/s]  ModifiedDissim:  70%|███████   | 19/27 [00:21<00:05,  1.44it/s]ModifiedGini:  70%|███████   | 19/27 [00:21<00:05,  1.44it/s]  ModifiedDissim:  70%|███████   | 19/27 [00:21<00:05,  1.44it/s]ModifiedGini:  70%|███████   | 19/27 [00:21<00:05,  1.44it/s]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:21<00:29,  1.97s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:21<00:29,  1.97s/it]  ModifiedDissim:  70%|███████   | 19/27 [00:21<00:05,  1.42it/s]ModifiedGini:  70%|███████   | 19/27 [00:21<00:05,  1.42it/s]  ModifiedDissim:  70%|███████   | 19/27 [00:21<00:05,  1.43it/s]ModifiedGini:  70%|███████   | 19/27 [00:21<00:05,  1.43it/s]  ModifiedDissim:  70%|███████   | 19/27 [00:21<00:05,  1.42it/s]ModifiedGini:  70%|███████   | 19/27 [00:21<00:05,  1.42it/s]  DistanceDecayInteraction:  44%|████▍     | 12/27 [00:21<00:29,  1.99s/it]DistanceDecayIsolation:  44%|████▍     | 12/27 [00:21<00:29,  1.99s/it]  DistanceDecayIsolation:  48%|████▊     | 13/27 [00:21<00:23,  1.68s/it]Entropy:  48%|████▊     | 13/27 [00:21<00:23,  1.68s/it]               Gini:  52%|█████▏    | 14/27 [00:21<00:21,  1.68s/it]   DistanceDecayIsolation:  48%|████▊     | 13/27 [00:21<00:23,  1.69s/it]Entropy:  48%|████▊     | 13/27 [00:21<00:23,  1.69s/it]               Gini:  52%|█████▏    | 14/27 [00:21<00:21,  1.69s/it]   Gini:  56%|█████▌    | 15/27 [00:23<00:16,  1.41s/it]Interaction:  56%|█████▌    | 15/27 [00:23<00:16,  1.41s/it]Isolation:  59%|█████▉    | 16/27 [00:23<00:15,  1.41s/it]  MinMax:  63%|██████▎   | 17/27 [00:23<00:14,  1.41s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:23<00:12,  1.41s/it]ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]   ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]   Gini:  56%|█████▌    | 15/27 [00:23<00:16,  1.41s/it]Interaction:  56%|█████▌    | 15/27 [00:23<00:16,  1.41s/it]Isolation:  59%|█████▉    | 16/27 [00:23<00:15,  1.41s/it]  MinMax:  63%|██████▎   | 17/27 [00:23<00:14,  1.41s/it]   ModifiedDissim:  67%|██████▋   | 18/27 [00:23<00:12,  1.41s/it]ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]   ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]   ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.07it/s]   ModifiedDissim:  70%|███████   | 19/27 [00:23<00:06,  1.31it/s]ModifiedGini:  70%|███████   | 19/27 [00:23<00:06,  1.31it/s]  ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]   ModifiedDissim:  70%|███████   | 19/27 [00:23<00:06,  1.31it/s]ModifiedGini:  70%|███████   | 19/27 [00:23<00:06,  1.31it/s]  ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]   ModifiedGini:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]PARDissim:  74%|███████▍  | 20/27 [00:23<00:06,  1.06it/s]   ModifiedGini:  74%|███████▍  | 20/27 [00:26<00:07,  1.06s/it]PARDissim:  74%|███████▍  | 20/27 [00:26<00:07,  1.06s/it]   ModifiedGini:  74%|███████▍  | 20/27 [00:26<00:07,  1.07s/it]PARDissim:  74%|███████▍  | 20/27 [00:26<00:07,  1.07s/it]   PARDissim:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]PARDissim:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:27<00:07,  1.59s/it]    RelativeClustering:  81%|████████▏ | 22/27 [00:27<00:07,  1.59s/it]    RelativeClustering:  85%|████████▌ | 23/27 [00:27<00:04,  1.09s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:27<00:04,  1.09s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:27<00:03,  1.09s/it]        RelativeClustering:  85%|████████▌ | 23/27 [00:27<00:04,  1.09s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:27<00:04,  1.09s/it]PARDissim:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:27<00:09,  1.59s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:27<00:03,  1.09s/it]        RelativeClustering:  81%|████████▏ | 22/27 [00:27<00:07,  1.59s/it]    PARDissim:  78%|███████▊  | 21/27 [00:28<00:09,  1.60s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:28<00:09,  1.60s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:28<00:07,  1.60s/it]    RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.09s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.09s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.09s/it]        PARDissim:  78%|███████▊  | 21/27 [00:28<00:09,  1.60s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:28<00:09,  1.60s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:28<00:08,  1.60s/it]    PARDissim:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:28<00:08,  1.63s/it]    PARDissim:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:28<00:08,  1.63s/it]    PARDissim:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:28<00:09,  1.63s/it]RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.10s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.10s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.10s/it]        RelativeClustering:  81%|████████▏ | 22/27 [00:28<00:08,  1.63s/it]    RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.10s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.10s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.10s/it]        RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.12s/it]        RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.12s/it]        RelativeClustering:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:28<00:04,  1.12s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:28<00:03,  1.12s/it]        SpatialDissim:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialProxProf:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialDissim:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialProxProf:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialDissim:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialProxProf:  93%|█████████▎| 25/27 [00:29<00:01,  1.02it/s]SpatialDissim:  93%|█████████▎| 25/27 [00:29<00:01,  1.01it/s]SpatialProxProf:  93%|█████████▎| 25/27 [00:29<00:01,  1.01it/s]SpatialDissim:  93%|█████████▎| 25/27 [00:29<00:02,  1.01s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:29<00:02,  1.01s/it]SpatialDissim:  93%|█████████▎| 25/27 [00:30<00:02,  1.01s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:30<00:02,  1.01s/it]SpatialDissim:  93%|█████████▎| 25/27 [00:30<00:02,  1.02s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:30<00:02,  1.02s/it]SpatialDissim:  93%|█████████▎| 25/27 [00:30<00:02,  1.01s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:30<00:02,  1.01s/it]PARDissim:  78%|███████▊  | 21/27 [00:31<00:10,  1.75s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:31<00:10,  1.75s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:31<00:08,  1.75s/it]    PARDissim:  78%|███████▊  | 21/27 [00:31<00:10,  1.74s/it]RelativeCentralization:  78%|███████▊  | 21/27 [00:31<00:10,  1.74s/it]RelativeClustering:  81%|████████▏ | 22/27 [00:31<00:08,  1.74s/it]    RelativeClustering:  85%|████████▌ | 23/27 [00:31<00:04,  1.21s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:31<00:04,  1.21s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:31<00:03,  1.21s/it]        RelativeClustering:  85%|████████▌ | 23/27 [00:31<00:04,  1.21s/it]RelativeConcentration:  85%|████████▌ | 23/27 [00:31<00:04,  1.21s/it]SpatialDissim:  89%|████████▉ | 24/27 [00:31<00:03,  1.21s/it]        SpatialDissim:  93%|█████████▎| 25/27 [00:34<00:02,  1.25s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:34<00:02,  1.25s/it]SpatialDissim:  93%|█████████▎| 25/27 [00:34<00:02,  1.30s/it]SpatialProxProf:  93%|█████████▎| 25/27 [00:34<00:02,  1.30s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:56<00:05,  5.84s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:56<00:05,  5.84s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:56<00:05,  5.87s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:56<00:05,  5.87s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:56<00:05,  5.86s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:56<00:05,  5.86s/it]SpatialProximity: 100%|██████████| 27/27 [00:56<00:00,  4.68s/it]SpatialProximity: 100%|██████████| 27/27 [00:56<00:00,  4.70s/it]SpatialProximity: 100%|██████████| 27/27 [00:56<00:00,  2.11s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.69s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.11s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.12s/it]
SpatialProxProf:  96%|█████████▋| 26/27 [00:57<00:05,  5.91s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:57<00:05,  5.91s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:57<00:05,  5.95s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:57<00:05,  5.95s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:57<00:05,  5.95s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:57<00:05,  5.95s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:57<00:05,  5.97s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:57<00:05,  5.97s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.71s/it]SpatialProxProf:  96%|█████████▋| 26/27 [00:57<00:05,  5.99s/it]SpatialProximity:  96%|█████████▋| 26/27 [00:57<00:05,  5.99s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.76s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.13s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.75s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.14s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.76s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.14s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  4.77s/it]SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.14s/it]
SpatialProximity: 100%|██████████| 27/27 [00:57<00:00,  2.14s/it]
SpatialProxProf:  96%|█████████▋| 26/27 [01:01<00:06,  6.16s/it]SpatialProximity:  96%|█████████▋| 26/27 [01:01<00:06,  6.16s/it]SpatialProximity: 100%|██████████| 27/27 [01:01<00:00,  4.91s/it]SpatialProximity: 100%|██████████| 27/27 [01:01<00:00,  2.30s/it]
SpatialProxProf:  96%|█████████▋| 26/27 [01:02<00:06,  6.36s/it]SpatialProximity:  96%|█████████▋| 26/27 [01:02<00:06,  6.36s/it]SpatialProximity: 100%|██████████| 27/27 [01:03<00:00,  5.07s/it]SpatialProximity: 100%|██████████| 27/27 [01:03<00:00,  2.34s/it]
year 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
Name
AbsoluteCentralization 0.6945 0.6943 0.6959 0.6941 0.6938 0.6942 0.6927 0.6892 0.6841 0.6804
AbsoluteClustering 0.3263 0.3256 0.3277 0.3293 0.3326 0.3386 0.3396 0.3427 0.3529 0.3613
AbsoluteConcentration 0.8278 0.8306 0.8313 0.8287 0.8284 0.8247 0.8215 0.8205 0.8279 0.8270
Atkinson 0.6294 0.6252 0.6195 0.6130 0.6069 0.6050 0.5986 0.5929 0.6151 0.6106
BiasCorrectedDissim 0.6523 0.6526 0.6502 0.6462 0.6443 0.6433 0.6400 0.6362 0.6495 0.6463
BoundarySpatialDissim 0.5239 0.5240 0.5217 0.5182 0.5191 0.5160 0.5106 0.5049 0.5017 0.4999
ConProf 0.6069 0.6081 0.6058 0.6023 0.6020 0.6023 0.6016 0.5965 0.6084 0.6068
CorrelationR 0.5192 0.5178 0.5137 0.5098 0.5065 0.5053 0.5019 0.4978 0.5134 0.5097
Delta 0.7937 0.7940 0.7944 0.7928 0.7921 0.7909 0.7883 0.7860 0.7958 0.7920
DensityCorrectedDissim 0.5064 0.5040 0.5063 0.4978 0.4942 0.4902 0.4935 0.4951 0.5171 0.5153
Dissim 0.6526 0.6529 0.6505 0.6464 0.6446 0.6436 0.6403 0.6366 0.6498 0.6466
DistanceDecayInteraction 0.4776 0.4778 0.4788 0.4800 0.4797 0.4788 0.4798 0.4805 0.4708 0.4707
DistanceDecayIsolation 0.5349 0.5351 0.5350 0.5356 0.5366 0.5394 0.5393 0.5397 0.5495 0.5523
Entropy 0.4665 0.4643 0.4598 0.4553 0.4511 0.4496 0.4454 0.4410 0.4577 0.4538
Gini 0.8248 0.8232 0.8202 0.8169 0.8137 0.8125 0.8092 0.8065 0.8193 0.8164
Interaction 0.3174 0.3178 0.3199 0.3217 0.3227 0.3222 0.3237 0.3252 0.3141 0.3144
Isolation 0.6826 0.6822 0.6801 0.6783 0.6773 0.6778 0.6763 0.6748 0.6859 0.6856
MinMax 0.7898 0.7900 0.7882 0.7852 0.7839 0.7831 0.7807 0.7779 0.7877 0.7854
ModifiedDissim 0.6443 0.6445 0.6421 0.6379 0.6362 0.6350 0.6318 0.6281 0.6410 0.6378
ModifiedGini 0.8185 0.8171 0.8140 0.8105 0.8073 0.8061 0.8027 0.8000 0.8128 0.8099
PARDissim 0.6379 0.6382 0.6358 0.6318 0.6303 0.6290 0.6258 0.6218 0.6357 0.6327
RelativeCentralization -0.0193 -0.0223 -0.0216 -0.0249 -0.0258 -0.0280 -0.0283 -0.0317 -0.0426 -0.0424
RelativeClustering 0.7093 0.7050 0.7178 0.7202 0.7241 0.7390 0.7369 0.7269 0.7330 0.7556
RelativeConcentration 0.6029 0.6118 0.6156 0.6116 0.6142 0.6089 0.6033 0.6043 0.6267 0.6299
SpatialDissim 0.5171 0.5172 0.5151 0.5112 0.5121 0.5095 0.5042 0.4999 0.4963 0.4943
SpatialProxProf 0.5772 0.5781 0.5808 0.5840 0.5896 0.5951 0.5980 0.6024 0.6019 0.6116
SpatialProximity 1.2668 1.2656 1.2651 1.2642 1.2650 1.2669 1.2653 1.2641 1.2788 1.2801

The segs_single result is a dataframe that stores computed segregation indices in each row for time periods in each column. As with the segregation profiles, this format makes it easy to plot all or a subset of indices over time.

Code
segs_single.T.hvplot(height=600)
Code
segs_single.loc[['Entropy', 'Isolation', 'AbsoluteClustering']].T.plot()

And it is also trivial to examine relative change over each time period.

Code
segs_single.T[
    ["Entropy", "Isolation", "AbsoluteClustering"]
].pct_change().round(3) *100
Name Entropy Isolation AbsoluteClustering
year
2012 NaN NaN NaN
2013 -0.5 -0.1 -0.2
2014 -1.0 -0.3 0.6
2015 -1.0 -0.3 0.5
2016 -0.9 -0.1 1.0
2017 -0.3 0.1 1.8
2018 -0.9 -0.2 0.3
2019 -1.0 -0.2 0.9
2020 3.8 1.6 3.0
2021 -0.9 -0.0 2.4

Here we can see segregation measured by Entropy and Isolation has decreased modestly each sampling period until the 2020 ACS, which introduced new geographic tabulation units. After this period, segregation increased sharply before decreasing once again. By contrast, the absolute clustring index shows a steady increase over all time periods.

17.3.2 Multi-Group Indices

Multi-group indices work in exactly the same fashion using the multigroup_tempdyn function and passing groups instead of the usual single group arguments.

Code
groups = [
    "n_nonhisp_white_persons",
    "n_nonhisp_black_persons",
    "n_hispanic_persons",
    "n_asian_persons",
]

multi_by_time = segdyn.multigroup_tempdyn(dc, groups)
multi_by_time
year 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
Name
GlobalDistortion 191.2887 187.7508 184.3600 180.4351 179.0859 176.8691 174.6430 171.7495 193.2095 195.9176
MultiDissim 0.5263 0.5240 0.5188 0.5169 0.5138 0.5119 0.5079 0.5053 0.5179 0.5151
MultiDivergence 0.3845 0.3819 0.3781 0.3761 0.3727 0.3738 0.3710 0.3693 0.3898 0.3900
MultiDiversity 1.1958 1.2019 1.2091 1.2154 1.2200 1.2271 1.2314 1.2361 1.2434 1.2499
MultiGini 0.6952 0.6915 0.6861 0.6827 0.6788 0.6770 0.6733 0.6701 0.6843 0.6816
MultiInfoTheory 0.3215 0.3177 0.3127 0.3094 0.3055 0.3046 0.3013 0.2987 0.3135 0.3120
MultiNormExposure 0.3315 0.3285 0.3231 0.3203 0.3169 0.3144 0.3108 0.3079 0.3180 0.3150
MultiRelativeDiversity 0.3196 0.3166 0.3118 0.3092 0.3061 0.3042 0.3010 0.2983 0.3089 0.3066
MultiSquaredCoefVar 0.2640 0.2627 0.2602 0.2598 0.2579 0.2588 0.2575 0.2566 0.2697 0.2700
SimpsonsConcentration 0.3503 0.3471 0.3434 0.3400 0.3375 0.3336 0.3312 0.3286 0.3249 0.3212
SimpsonsInteraction 0.6497 0.6529 0.6566 0.6600 0.6625 0.6664 0.6688 0.6714 0.6751 0.6788

And once again we can plot all indices:

Code
multi_by_time.iloc[1:].T.plot()

Most indices are changing little over time, but most have followed the same trend with a mild drop in 2016 prior to a slight increase in the latest available data

Code
fig, axs = plt.subplots(1, 2, figsize=(8, 3))

multi_by_time.loc["MultiInfoTheory"].plot(ax=axs[0])
multi_by_time.loc["MultiInfoTheory"].plot(kind="bar", ax=axs[1])

fig.suptitle("Multigroup Information Theory")
Text(0.5, 0.98, 'Multigroup Information Theory')

When examining change over time it can be useful to use more than one plot sometimes. The line plots are good at showing relative change between each period, while the bar plots help give a sense of the absolute difference over time.

Code
fig, axs = plt.subplots(1, 2, figsize=(8, 3))

multi_by_time.loc["MultiNormExposure"].plot(ax=axs[0])
multi_by_time.loc["MultiNormExposure"].plot(kind="bar", ax=axs[1])

fig.suptitle("Multigroup Isolation/Exposure")
Text(0.5, 0.98, 'Multigroup Isolation/Exposure')

Code
multi_by_time.T[
    ["MultiInfoTheory", "MultiNormExposure"]
].pct_change().round(3) * 100
Name MultiInfoTheory MultiNormExposure
year
2012 NaN NaN
2013 -1.2 -0.9
2014 -1.6 -1.6
2015 -1.1 -0.9
2016 -1.3 -1.1
2017 -0.3 -0.8
2018 -1.1 -1.1
2019 -0.9 -0.9
2020 5.0 3.3
2021 -0.5 -0.9

17.4 Space-Time Dynamics

One way to consider spatiotemporal segregation dynamics is computing multiscalar profiles for successive time periods (Reardon et al., 2009). Stacking these horizontally results in a space-time matrix of segregation measures; looking across rows describes how segregation changes over time at a particular spatial scale whereas looking down rows describes how segregation changes over scale at each time period. As usual, one of the best ways to understand this is to plot the profiles on a single graph but use color to denote change over time.

Code
d = segdyn.spacetime_dyn(
    dc,
    singlegroup.Entropy,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="blackwhite",
    distances=list(range(500, 5500, 500)),
)
iso = segdyn.spacetime_dyn(
    dc,
    singlegroup.Isolation,
    group_pop_var="n_nonhisp_black_persons",
    total_pop_var="blackwhite",
    distances=list(range(500, 5500, 500)),
)

f, ax = plt.subplots(1, 2, figsize=(8, 4))

d.plot(cmap="viridis_r", ax=ax[0])
iso.plot(cmap="viridis_r", ax=ax[1])

ax[0].set_title("Entropy Index")
ax[1].set_title("Isolation Index")

plt.tight_layout()

Entropy and Isolation are falling the fastest at large scales, with a wider gap on the right-hand side of the graph than the left-hand side. Further, for both indices, the slope of the segregation profile has become steeper over time, specifically within the last two years of data (those based on 2020 census geographic units).