Choropleth maps#

Choropleth maps represent a continuous or ordinal variable using a color assigned to each geometry. GeoPandas can create choropleth maps natively by passing the column containing those values to the column argument of the plot() method.

Loading some example data:

In [1]: import geodatasets

In [2]: south = geopandas.read_file(
   ...:     geodatasets.get_path("geoda.south")
   ...: )
   ...: 

Default behavior#

The dataset contains counties in southern US states, with sociodemographic data associated with each county. To plot the percentage of female-headed households in 1990, pass its column name, "FH90", to column:

In [3]: south.plot(column='FH90');
../../_images/south.png

If you would like to show a legend, pass legend=True. By default, this will create a colorbar.

In [4]: south.plot(column='FH90', legend=True);
../../_images/south_legend.png

The default color mapping stretches the colors from the minimum to the maximum of the observed values. These bounds can be customized with the vmin and vmax keywords, which specify the minimum and maximum values respectively. In that case, the colorbar indicates that some values go beyond the extremes.

In [5]: south.plot(column='FH90', legend=True, vmax=30);
../../_images/south_vmax.png

Classification schemes#

The default mapping of values to colors is continuous and linear which may not provide an optimal cartographic visualization of the data. The mapping can be adjusted using the scheme keyword, which specifies a classification scheme. You can, for example, map colors to quantiles, where each color bin contains the same number of geometries. Note that using scheme requires the optional mapclassify dependency.

In [6]: south.plot(column='FH90', legend=True, scheme='quantiles');
../../_images/south_quantiles.png

This changes the mapping of colors but, by default, also changes the style of the legend. This default exists for legacy reasons and can be useful on its own. However, a more suitable option is often to keep the colorbar, which you can request with legend_kwds.

In [7]: south.plot(
   ...:     column='FH90',
   ...:     legend=True,
   ...:     scheme='quantiles',
   ...:     legend_kwds={"colorbar": True},
   ...: );
   ...: 
../../_images/south_scheme_cbar.png

There are two options for spacing colors in the colorbar. The default is proportional spacing, where each bin gets a portion of the colorbar proportional to the range of values it represents. When bin edges are densely packed around the same values, this can yield a suboptimal result. In that case, it may be more useful to use uniform spacing, where each bin gets an equal portion of the colorbar and each color has enough space.

In [8]: south.plot(
   ...:     column='FH90',
   ...:     legend=True,
   ...:     scheme='quantiles',
   ...:     legend_kwds={"colorbar": True, "spacing": "uniform"},
   ...: );
   ...: 
../../_images/south_scheme_cbar_uniform.png

Most schemes support the k argument, which indicates the number of bins to use. Larger values are recommended when using a colorbar legend.

In [9]: south.plot(
   ...:     column='FH90',
   ...:     legend=True,
   ...:     scheme='quantiles',
   ...:     k=10,
   ...:     legend_kwds={"colorbar": True},
   ...: );
   ...: 
../../_images/south_scheme_k.png

Classification schemes are provided by the mapclassify package, and any of its supported schemes can be used here. The current options include:

  • "BoxPlot"

  • "EqualInterval"

  • "FisherJenks"

  • "FisherJenksSampled"

  • "HeadTailBreaks"

  • "JenksCaspall"

  • "JenksCaspallForced"

  • "JenksCaspallSampled"

  • "MaxP"

  • "MaximumBreaks"

  • "NaturalBreaks"

  • "Percentiles"

  • "PrettyBreaks"

  • "Quantiles"

  • "StdMean"

  • "UserDefined"

Different classification schemes can emphasize different patterns in the same data.

In [10]: fig, axs = plt.subplots(2, 2)

In [11]: schemes = ["EqualInterval", "Quantiles", "NaturalBreaks", "FisherJenks"]

In [12]: for scheme, ax in zip(schemes, axs.flat):
   ....:     south.plot(
   ....:         column="FH90",
   ....:         scheme=scheme,
   ....:         legend=True,
   ....:         legend_kwds={"colorbar": True},
   ....:         ax=ax)
   ....:     ax.set_title(scheme)
   ....:     ax.set_axis_off()
   ....: 

In [13]: plt.tight_layout()
../../_images/schemes.png

GeoPandas also supports scheme="greedy", which uses mapclassify.greedy() to derive a topological coloring where neighboring geometries do not share the same color. This scheme cannot be used together with column because it does not classify attribute values.

In [14]: south.plot(scheme="greedy", cmap="Set3");
../../_images/greedy.png

Arguments for the classification scheme can be passed as a dictionary to classification_kwds. See the mapclassify documentation for details on the available schemes and their parameters.

In [15]: south.plot(
   ....:     column="FH90",
   ....:     legend=True,
   ....:     scheme="UserDefined",
   ....:     classification_kwds={
   ....:         "bins": [10, 20, 30],
   ....:         "lowest": 0
   ....:     },
   ....:     legend_kwds={"colorbar": True},
   ....: );
   ....: 
../../_images/class_kwds.png

Colormaps#

The colormap used in the choropleth map can be any string recognized by Matplotlib or any matplotlib.colors.Colormap object.

In [16]: fig, axs = plt.subplots(2, 2, sharex=True, sharey=True)

In [17]: cmaps = ["viridis", "cividis", "plasma", "managua"]

In [18]: for cmap, ax in zip(cmaps, axs.flat):
   ....:     south.plot(column='FH90', cmap=cmap, ax=ax, add_labels=False)
   ....:     ax.set_title(cmap)
   ....: 

In [19]: plt.tight_layout()
../../_images/cmaps.png