DJV
DJV

Reputation: 873

Legends in Matplotlib Basemap

I'm plotting multiple points in Basemap and would like to have a legend to signify the category that each color represents. However, since I have multiple points in each category, the legend pulls each of those points, giving me multiple entries of the same category in the legend. Is there a way to just show one overall color-category listing?

m = Basemap(llcrnrlon=30.,llcrnrlat=20.,urcrnrlon=-160.,urcrnrlat=63.,projection='lcc',resolution='c',lat_1=20.,lat_2=40.,lon_0=90.,lat_0=50.)

X,Y = m(lon,lat)    
m.drawcountries()
m.drawmapboundary(fill_color='lightblue')
m.drawparallels(np.arange(0.,90.,5.),color='gray',dashes=[1,3],labels=[1,0,0,0])
m.drawmeridians(np.arange(0.,360.,15.),color='gray',dashes=[1,3],labels=[0,0,0,1])
m.fillcontinents(color='beige',lake_color='lightblue')
plt.title('MERRA-Observation Correlations')

for j in range(len(corr)):
    if j == 0 or j == 1 or j ==2:
        m.plot(X[j],Y[j],'o',color='orange',markersize=np.absolute(corr[j])*17.5,label='Prairie')
    if j == 3 or j ==4 or j == 5:
        m.plot(X[j],Y[j],'o',color='violet',markersize=np.absolute(corr[j])*17.5,label='Tundra')
    if j ==6 or j == 7 or j == 8:
        m.plot(X[j],Y[j],'o',color='purple',markersize=np.absolute(corr[j])*17.5,label='Taiga')
    plt.legend()

NOTE: I've placed plt.legend both inside and outside the loop with the same results.

enter image description here

Upvotes: 1

Views: 9998

Answers (3)

cphlewis
cphlewis

Reputation: 16249

Another way: replace your call to plt.legend() with this and do it outside the for-loop:

ax = plt.gca()
handles, labels = ax.get_legend_handles_labels()
legend = plt.legend([handles[0],handles[3],handles[6]], labels[0],labels[3],labels[6]])

this pulls apart the stuff that's set up by plot (scatter, etc) calls to be sent to legend, so you can see how you might alter legends differently.

xnx's scatter solution also looks good.

p.s. -- this doesn't have anything to do with basemap, it's general to matplotlib plotting.

Upvotes: 1

xnx
xnx

Reputation: 25518

You seem to be plotting a whole new line for each data point. A scatter plot might be more appropriate: instead of your j loop, try:

scale = 17.5
m.scatter(X[:3], Y[:3], color='orange', s=abs(corr[:3])*scale, label='Prairie')
m.scatter(X[3:6], Y[3:6], color='violet', s=abs(corr[3:6])*scale, label='Tundra')
m.scatter(X[6:], Y[6:], color='purple', s=abs(corr[6:])*scale, label='Taiga')

(untested: I don't have your data).

Upvotes: 3

AMacK
AMacK

Reputation: 1396

Instead of passing the legend kwarg, you can retain a handle to the object returned by m.plot. You can then create the legend manually with only the plots you want to keep.

how to add legend for scatter()? has a good example.

Upvotes: 1

Related Questions