¿Cómo mostrar la etiqueta de shapefile en la leyenda del mapa base de python?

El mapa base de python tiene dos contenidos trazados: un shapefile multilínea (IL_State_ln) y un diagtwig de dispersión de algunos puntos aleatorios dentro de la extensión del mapa base. Mi interés está en generar una leyenda que brinde información sobre el shapefile y los puntos de dispersión. Por ahora, solo puedo incluir los puntos en la leyenda y no el shapefile.

La comprobación de la documentación de la API de mapa base no proporciona ninguna información, ya que la función readshapefile () no parece tener ningún argumento de etiqueta .

¿Podría ayudarme, por favor, a incluir el indicador de shapefile en la leyenda como en los mapas de ArcGIS?

Aquí está mi código:

import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.basemap import Basemap fname = "DATA/GIS/IL_State_ln" m = Basemap(llcrnrlon=-92.,llcrnrlat=36.8,urcrnrlon=-86.5,urcrnrlat=43., resolution='i', projection='tmerc', lat_0 = 36.5, lon_0 = -91.8) m.readshapefile(fname, 'mygeom') x,y = m([-90., -91.2, -88.], [38., 37.7, 42.]) m.scatter(x,y, marker='o', label="Points") plt.legend(loc=3) plt.show() 

Estoy usando Python 3.5, matplotlib 2.0 y basemap 1.0.8.

La idea de crear una entrada de leyenda sería dibujar las formas como polígonos, que luego se pueden agregar a la leyenda.
Por lo tanto, primero desactivamos los drawbounds , m.readshapefile(fn, 'shf', drawbounds = False) . Luego, podemos crear un matplotlib.patches.Polygon desde el matplotlib.patches.Polygon de forma y agregarlo a los ejes, plt.gca().add_artist(polygon) .

La leyenda puede ser actualizada usando este polígono.

 handles, labels = plt.gca().get_legend_handles_labels() handles.extend([polygon]) labels.extend(["Name of the shape"]) plt.legend(handles=handles, labels=labels) 

Aquí hay ahora un código en acción, que produce las siguientes imágenes. Utiliza el archivo ne_10m_admin_0_countries .

introduzca la descripción de la imagen aquí

 from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from matplotlib.patches import Polygon import numpy as np m = Basemap(llcrnrlon=-10,llcrnrlat=35,urcrnrlon=35,urcrnrlat=60., resolution='i', projection='tmerc', lat_0 = 48.9, lon_0 = 15.3) m.drawcoastlines() m.drawcountries(zorder=0, color=(.9,.9,.9), linewidth=1) fn = r"ne_10m_admin_0_countries\ne_10m_admin_0_countries" m.readshapefile(fn, 'shf', drawbounds = False) #Madrid x,y = m([-3.703889],[40.4125]) m.plot(x,y, marker="o", color="blue", label="Madrid", ls="") # some countries countries = ['Switzerland', 'Ireland', "Belgium"] colors= {'Switzerland':"red", 'Ireland':"orange", 'Belgium' : "purple"} shapes = {} for info, shape in zip(m.shf_info, m.shf): if info['NAME'] in countries: p= Polygon(np.array(shape), True, facecolor= colors[info['NAME']], edgecolor='none', alpha=0.7, zorder=2) shapes.update({info['NAME'] : p}) for country in countries: plt.gca().add_artist(shapes[country]) # create legend, by first getting the already present handles, labels handles, labels = plt.gca().get_legend_handles_labels() # and then adding the new ones handles.extend([shapes[c] for c in countries]) labels.extend(countries) plt.legend(handles=handles, labels=labels, framealpha=1.) plt.show() 

Ahora porque ya tenemos un polígono con la forma, ¿por qué no hacer que la leyenda sea un poco más elegante, al trazar directamente la forma en la leyenda? Esto puede hacerse de la siguiente manera.

introduzca la descripción de la imagen aquí

 from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from matplotlib.patches import Polygon import numpy as np m = Basemap(llcrnrlon=-10,llcrnrlat=35,urcrnrlon=35,urcrnrlat=60., resolution='i', projection='tmerc', lat_0 = 48.9, lon_0 = 15.3) m.drawcoastlines() fn = r"ne_10m_admin_0_countries\ne_10m_admin_0_countries" m.readshapefile(fn, 'shf', drawbounds = False) #Madrid x,y = m([-3.703889],[40.4125]) m.plot(x,y, marker="o", color="blue", label="Madrid", ls="") countries = ['Switzerland', 'Ireland', "Belgium"] colors= {'Switzerland':"red", 'Ireland':"orange", 'Belgium' : "purple"} shapes = {} for info, shape in zip(m.shf_info, m.shf): if info['NAME'] in countries: p= Polygon(np.array(shape), True, facecolor= colors[info['NAME']], edgecolor='none', alpha=0.7, zorder=2) shapes.update({info['NAME'] : p}) for country in countries: plt.gca().add_artist(shapes[country]) class PolygonN(object): def legend_artist(self, legend, orig_handle, fontsize, handlebox): x0, y0 = handlebox.xdescent, handlebox.ydescent width, height = handlebox.width, handlebox.height aspect= height/float(width) verts = orig_handle.get_xy() minx, miny = verts[:,0].min(), verts[:,1].min() maxx, maxy = verts[:,0].max(), verts[:,1].max() aspect= (maxy-miny)/float((maxx-minx)) nvx = (verts[:,0]-minx)*float(height)/aspect/(maxx-minx)-x0 nvy = (verts[:,1]-miny)*float(height)/(maxy-miny)-y0 p = Polygon(np.c_[nvx, nvy]) p.update_from(orig_handle) p.set_transform(handlebox.get_transform()) handlebox.add_artist(p) return p handles, labels = plt.gca().get_legend_handles_labels() handles.extend([shapes[c] for c in countries]) labels.extend(countries) plt.legend(handles=handles, labels=labels, handleheight=3, handlelength=3, framealpha=1., handler_map={Polygon: PolygonN()} ) plt.show()