Search code examples
pythonpandasmatplotlibgeopandas

geopandas plotting with legend filled up with slash lines


I use different colors and patterns to show three counties on the PA map. The Centre County is represented by the slash lines using hatch='\\'. But I got difficulties to show such pattern on the legend.

I kind of know that this is not going to work, but I tried Line2D([0],[0],color='white',hatch='\\',lw=4,label='Centre County'), and got errors saying something like "hatch is not an attribute".

%matplotlib inline

import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

fig, ax = plt.subplots(1,figsize=(8,8))

pa.plot(ax=ax,color='white',edgecolor='grey')
centre.plot(ax=ax,color='white',hatch='\\\\\\\\',edgecolor='black')
pike.plot(ax=ax,color='grey')
perry.plot(ax=ax,color='red')

LegendElement = [
                 Line2D([0],[0],color='red',lw=4,label='Perry County'),
                 Line2D([0],[0],color='grey',lw=4,label='Pike County'),
                 Line2D([0],[0],color='white',lw=4,label='Centre County')
                ]
ax.legend(handles=LegendElement,loc='upper right')

enter image description here


Solution

  • When you create polygons, the property facecolor defines the fill color. And to create correct legend for polygon features, mpatches.Patch is needed.

    Here is the code that demonstrates how to use facecolor, and mpatches.Patch:

    import geopandas as gpd
    import matplotlib.pyplot as plt
    #from matplotlib.lines import Line2D
    import matplotlib.patches as mpatches
    from cartopy import crs as ccrs
    
    #fig, ax = plt.subplots(1,figsize=(8,8))
    fig, ax = plt.subplots(figsize=(9,9), subplot_kw={'projection': ccrs.PlateCarree()})
    
    world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
    # cities = gpd.read_file(gpd.datasets.get_path('naturalearth_cities'))
    
    asia = world[(world.continent == "Asia")]  #take Asia countries
    asia.plot(ax=ax, color="lightgreen")
    
    china = asia[(asia.name == "China")]
    india = asia[(asia.name == "India")]
    saudi = asia[(asia.name == "Saudi Arabia")]
    
    
    ax.add_geometries(china['geometry'], crs=ccrs.PlateCarree(), \
                          facecolor='w', hatch='\\\\\\\\', edgecolor='k', label='China')
    ax.add_geometries(india['geometry'], crs=ccrs.PlateCarree(), \
                          color='grey', label='India')
    ax.add_geometries(saudi['geometry'], crs=ccrs.PlateCarree(), \
                          color='red', label='Saudi Arabia')
    
    LegendElement = [
                     mpatches.Patch(facecolor='w', hatch='\\\\\\\\', edgecolor='k', label='China'),
                     mpatches.Patch(color='grey', label='India'),
                     mpatches.Patch(color='red', label='Saudi Arabia')
                    ]
    ax.legend(handles = LegendElement, loc='upper right')
    plt.show()
    

    The output plot looks like this:

    enter image description here