1

I am trying to plot 9 geopandas.GeoDataFrames which are stored in a dictionary. As they share the same legend, I would like to get handles and labels to plot only one legend beside the maps.

fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(16,6), sharex=True, sharey=True)
for eix, key in zip(axes.flat, maps.keys()):
  maps[key].plot(ax=eix,
                 column='NAMES')

I have tried to follow this question, doing:

handles, labels = ax.get_legend_handles_labels()
fig.legend(handles, labels, bbox_to_anchor=(1.05, 1), loc='upper center')

but without success. handles and labels returned empty lists when I used ax.get_legend_handles_labels() inside and outside the loop.

If I try:

fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(16,6), sharex=True, sharey=True)

for eix, key in zip(axes.flat, maps.keys()):
  maps[key].plot(ax=eix,
                 column='NAMES',
                 legend=True);

I get one legend for each map, but it is not what I want. So, does anyone have any suggestions?

Code example with 4 GeoDataFrames:

import pandas as pd
import numpy as np
import geopandas as gpd
import matplotlib.pyplot as plt

### THE CODE BELOW IS JUST TO CREATE THE DICTIONARY WITH GEOPANDAS.GEODATAFRAMES

# I uploaded a geopandas dataset just to exemplify
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))

#creating meaningless classes to have a dictionary with the same characteristics as my real dic 

world.replace({'continent' : { 'Oceania': 'A', 'Africa': 'B', 'North America': 'C', 'Asia': 'D', 'South America': 'E',
       'Europe': 'F', 'Seven seas (open ocean)': np.NaN, 'Antarctica': 'G'}}, inplace=True)
world['cont_class']=world.continent

world['pop_class']=pd.cut(world['pop_est'],
                    bins=[0, 500000, 1000000, 5000000, 10000000, 50000000, 100000000, 500000000],
                    include_lowest=True,
                    labels=['A','B','C', 'D', 'E', 'F', 'G'],
                    right=True)

world['gdp_class']=pd.cut(world['gdp_md_est'],
                    bins=[0, 810, 250000, 500000, 1000000, 5000000, 20000000],
                    include_lowest=True,
                    labels=['A','B','C', 'D', 'E', 'F'],
                    right=True)

world['A_class']=pd.cut(world.index,
                    bins=7,
                    include_lowest=True,
                    labels=['A','B','C', 'D', 'E', 'F', 'G'],
                    right=True)

# creating the dictionary
class_names = ['cont_class', 'pop_class', 'gdp_class', 'A_class']

maps = {name: gpd.GeoDataFrame() for name in class_names}

for key in maps.keys():
  maps[key]=world
  maps[key]=maps[key].assign(NAMES=world[key])

### THE CODE ABOVE IS JUST TO CREATE THE DICTIONARY WITH GEOPANDAS.GEODATAFRAMES

# Question code starts here:
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(16,6), sharex=True, sharey=True)
for eix, key in zip(axes.flat, maps.keys()):
  maps[key].plot(ax=eix,
                 column='NAMES')
  handles, labels = eix.get_legend_handles_labels()

fig.legend(handles, labels, bbox_to_anchor=(1.05, 1), loc='upper center');
Marlon
  • 13
  • 4
  • 1
    `maps` is not defined (as are many other variables) – Paul H Dec 11 '20 at 04:21
  • @Paul H, I think only `maps` is missing, no other variables. 'maps' is a dictionary with `GeoDataFrames` stored in it. In addition to `maps`, libraries still need to be imported. I will update the question with a code example. – Marlon Dec 16 '20 at 16:46

0 Answers0