Quick Start: Create Your First Voronoi Cartogram¶
Get started with the Voronoi cartogram module by building an equal-area and a population cartogram of US States.
What You'll Learn¶
- How to create an equal-area Voronoi cartogram with
create_voronoi_cartogram - How to add population weights so cell area reflects a data variable
- How to plot and label results, and read basic convergence metrics
Prerequisites¶
Install carto-flow first:
# Install prerequisites (run once in your terminal)
# pip install carto-flow
Step 1: Import Libraries¶
import matplotlib.pyplot as plt
import carto_flow.data as examples
import carto_flow.voronoi_cartogram as vor
Step 2: Load Geographic Data¶
Load population and geometry data for the lower 48 US States.
us_states = examples.load_us_census(population=True)
us_states.head()
| Population | STATE | State Abbreviation | State Name | geometry | Region | Division | Population (Millions) | Population Density | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 12794885 | 42 | PA | Pennsylvania | POLYGON ((1200847.835 331701.964, 1203743.68 3... | Northeast | Middle Atlantic | 12.794885 | 109.040186 |
| 1 | 39346023 | 06 | CA | California | MULTIPOLYGON (((-1979058.42 -528956.745, -1975... | West | Pacific | 39.346023 | 96.001918 |
| 2 | 1807426 | 54 | WV | West Virginia | POLYGON ((1100235.176 -108059.819, 1102295.003... | South | South Atlantic | 1.807426 | 28.802429 |
| 3 | 3151239 | 49 | UT | Utah | POLYGON ((-1396894.253 368735.242, -1392505.21... | West | Mountain | 3.151239 | 14.331142 |
| 4 | 19514849 | 36 | NY | New York | MULTIPOLYGON (((1253147.537 375607.401, 125587... | Northeast | Middle Atlantic | 19.514849 | 153.727217 |
Let's plot the original map colored by population to establish a baseline.
fig, ax = plt.subplots(figsize=(10, 6))
us_states.plot(
"Population (Millions)",
ax=ax,
legend=True,
cmap="RdYlGn_r",
legend_kwds={"shrink": 0.6, "label": "Population (Millions)"},
linewidth=0.5,
)
ax.set(title="US States — Population (original geography)")
ax.axis("off")
plt.tight_layout();
Step 3: Create an Equal-Area Voronoi Cartogram¶
Calling create_voronoi_cartogram without weights runs Lloyd relaxation until every Voronoi cell has the same area. The default RasterBackend labels pixels on a raster grid.
result_equal = vor.create_voronoi_cartogram(us_states)
Step 4: Plot the Equal-Area Result¶
Each state occupies an equal-area cell. Coloring by population reveals which states are over- or under-represented in the original geography.
fig, ax = plt.subplots(figsize=(10, 6))
result_equal.plot(
column="Population (Millions)",
legend=True,
cmap="RdYlGn_r",
legend_kwds={"shrink": 0.6, "label": "Population (Millions)"},
ax=ax,
)
for cell, label in zip(result_equal.cells, us_states["State Abbreviation"], strict=False):
ax.text(cell.centroid.x, cell.centroid.y, label, fontsize=7, ha="center", va="center")
ax.set(title="US States — Equal-Area Voronoi Cartogram")
ax.axis("off")
plt.tight_layout();
Step 5: Create a Population Voronoi Cartogram¶
Passing weights makes each cell's area proportional to the corresponding column. Large-but-sparsely-populated states (Montana, Wyoming) shrink; densely-populated ones (California, Texas, New York) expand.
result = vor.create_voronoi_cartogram(
us_states,
weights="Population (Millions)",
)
fig, ax = plt.subplots(figsize=(10, 6))
result.plot(
column="Population (Millions)",
legend=True,
cmap="RdYlGn_r",
legend_kwds={"shrink": 0.6, "label": "Population (Millions)"},
ax=ax,
)
for cell, label in zip(result.cells, us_states["State Abbreviation"], strict=False):
ax.text(cell.centroid.x, cell.centroid.y, label, fontsize=7, ha="center", va="center")
ax.set(title="US States — Voronoi Cartogram (area ∝ population)")
ax.axis("off")
plt.tight_layout();
Step 6: Read the Metrics¶
The metrics dict summarizes the run. final_area_cv is the area coefficient of variation — lower means cells are closer to their target areas. mean_area_error_pct is the average percentage deviation per region.
print(f"Converged: {result.metrics['converged']}")
print(f"Iterations: {result.metrics['n_iterations']}")
print(f"Final area CV: {result.metrics['final_area_cv']:.4f}")
print(f"Mean area error: {result.metrics['mean_area_error_pct']:.1f}%")
Converged: False Iterations: 30 Final area CV: 0.3122 Mean area error: 82.8%
Next Steps¶
- Choose the Right Backend — compare RasterBackend and ExactBackend: speed, accuracy, and when each is appropriate
- Coastal and Peninsula Regions — use
distance_mode="geodesic"to prevent pixel assignments across water bodies - Inspect and Improve Convergence — read convergence curves, area errors, and displacement; tune iteration count and relaxation schedule
- Analyze and Fix Topology — detect and repair satellite cells when working with grouped sub-regions
- Customize the Boundary — change the outer clipping shape and switch between fixed, adhesive, and elastic boundary behavior