Quick Start: Create Your First Symbolic Cartogram¶
Get started with carto-flow by creating a population cartogram in just a few lines of code.
What You'll Learn¶
- How to download population and geographic data from the US Census Bureau
- How to create a basic symbol cartogram from geographic data using the
create_symbol_cartogramfunction - How to visualize the symbol cartogram
Prerequisites¶
Install carto-flow first. For the examples, we use data from the US Census Bureau. The censusdis package offers a convenient interface for downloading this data.
# Install prerequisites (run this once in your terminal)
# pip install carto-flow
# pip install censusdis
Step 1: Import Libraries¶
import matplotlib.pyplot as plt
import carto_flow.data as examples
import carto_flow.symbol_cartogram as smb
Step 2: Load Geographic Data¶
Load population and geometry data for the lower 48 US States from the US Census Bureau data repository.
us_states = examples.load_us_census(population=True, simplify=200)
The us_states variable is a GeoPandas DataFrame, with for each US State the requested variables, the computed population density, and its geometry.
Let's plot a color map of the population in each state. GeoPandas DataFrames have a convenient plot method that we use here to create a choropleth map in which colors represent the size of a State's population.
fig, ax = plt.subplots(1, 1, figsize=(7, 6))
us_states.plot(
"Population (Millions)",
ax=ax,
vmin=0,
legend=True,
legend_kwds={"shrink": 0.6, "label": "Population (Millions)"},
cmap="YlOrRd",
edgecolor="black",
linewidth=0.5,
)
ax.axis("off")
plt.tight_layout()
plt.show()
Step 3: Create Symbolic Cartogram¶
In a symbolic cartogram, each geographical region is represented by a symbol, such as a circle, a square, or another shape. The symbols are either sized uniformly or proportionally to a variable of interest, such as the number of people living in the region.
A major challenge is to determine where to place the symbols to create a clear and informative cartogram. Positioning symbols at the centroid of their corresponding geographical region preserves the spatial arrangement that makes the map recognizable, but also often produces overlapping symbols or large spacing between symbols. Other options for the placement of the symbols include symbol packing to remove overlap and large spacing while attempting to preserve some of the topological relations between the symbols, and creating a more schematic cartogram by positioning symbols on a regular grid. All three methods are supported by the module.
Symbols at Region Centroids¶
Here we construct a cartogram in which each US State is represented by a circle that is located at the State's centroid, and has an area that is proportional to the values in the Population column of the us_states Dataframe. We let the CentroidLayout remove any overlap between the circles by locally pushing the circles apart.
symbol_carto = smb.create_symbol_cartogram(
us_states,
# provide a column for proportional sizing of the symbols
"Population",
# place symbols at the state centroids and remove overlap
layout=smb.CentroidLayout(remove_overlap=True),
)
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
_ = symbol_carto.plot(
ax=ax,
# color by population size
column="Population (Millions)",
# shrink the colorbar
legend_kwds={"shrink": 0.5},
# label the largest states
# we use the State abbreviation look-up table in the censusdis package
label=[
row["State Abbreviation"] if row["State Abbreviation"] in ["CA", "TX", "FL", "NY"] else ""
for _, row in us_states.iterrows()
],
)
Symbols on a Grid¶
Here we construct a cartogram in which each US State is represented by a (hexagon-shaped) symbol in a hexagon tiling grid. Each State is assigned to a tile in the grid such that it is close to its geographical centroid and close to its neighbors. By not passing in a Dataframe column name, we choose to give all symbols the same size.
symbol_carto = smb.create_symbol_cartogram(
us_states,
# provide a column for proportional sizing of the symbols
# "Population",
layout=smb.GridBasedLayout(tiling=smb.HexagonTiling()),
)
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
_ = symbol_carto.plot(
ax=ax,
# color by population size
column="Population (Millions)",
# shrink the colorbar
legend_kwds={"shrink": 0.75},
# label all states
# we use the State abbreviation look-up table in the censusdis package
label=us_states["State Abbreviation"],
# set label color to white and use bold font
label_color="w",
label_kwargs={"fontweight": "bold"},
)
Circle Packing¶
Here we construct a cartogram in which US States are represented by circles that are closely packed in such a way to preserve the topological structure of the original geometries. Circles are sized proportionally to the values in the Population column of the us_states Dataframe.
symbol_carto = smb.create_symbol_cartogram(
us_states,
# provide a column for proportional sizing of the symbols
"Population",
# use a physics-based circle packing layout
layout=smb.CirclePackingLayout(),
size_normalization="total",
)
Refining topology: 42%|██ | 211/500 [00:00<00:00, 315.81it/s, drift=5.47e-03, jitter=3.95e-02, overlaps=34]
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
_ = symbol_carto.plot(
ax=ax,
# color by population size
column="Population (Millions)",
# shrink the colorbar
legend_kwds={"shrink": 0.75},
# label all states
# use the State abbreviation look-up table in the censusdis package
label=us_states["State Abbreviation"],
# set label color to white and use small bold font
label_color="w",
label_kwargs={"fontweight": "bold"},
label_fontsize=7,
)
Additional Resources¶
This notebook is part of the carto-flow documentation. Report issues at https://github.com/bright-fakl/carto-flow/issues