Basemap: Get all data points on colorbar which each point refelecting the ploted color

Question:

I have a dataset, containing different types of trees in numerical i.e

Types = 4,8,9,10,13,15,19,33

I am plotting these types on a scatter plot, each type being represented by a different color. I can’t figure out a way for the color bar to represent the data correctly. So that it looks like this.

enter image description here

The color bar ticks should only represent the data plotted with each color representing a type. i.e

Green = 4
Orange = 8
etc

The plot below is my failed attempt at doing this. The colorbar ticks do not represent the vegetation plotted but a range.

fig = plt.figure()
plt.figure(figsize=(25,10))
m=Basemap(projection='mill',llcrnrlat=25,llcrnrlon=-130,urcrnrlat=49,urcrnrlon=-104.5,resolution='l')
m.drawcoastlines()
m.drawcountries()
m.drawstates()
x,y=m(list(Y60['col']),list(Y60['row']))
m.scatter(x,y,c=Y60['potveg'],s=Y60['potveg']*5,cmap='Dark2')
cbar=plt.color bar()

Types ploted

Thanks

Asked By: Jared Kodero

||

Answers:

My answer focuses on the steps to create the legend. Read the comments in the code for explanation.

import matplotlib.pyplot as plt

# Each item of legends requires 3 propereties: color/label_text/marker_shape
colors = ["green", "orange", "purple", "red", "lightgreen", "gray"]
texts = ["4", "9", "13", "15", "19", "33"]
markers = ["o", "o", "o", "o", "o", "o"]
len0 = len(colors)

# Points' locations and attributes
xs = [3,2,4,5,4,2,7,3]
ys = [41,12,32,15,35,21,23,43]
colors1 = ["green", "orange", "purple", "red", "lightgreen", "gray", "green", "orange"]
texts1 = ["4", "9", "13", "15", "19", "33", "4", "9"]
markers1 = ["o", "o", "o", "o", "o", "o", "o", "o"]
sizes1 = [8,16,9,12,7,4,10,6]
len1 = len(xs)

# Plot `none` data point and 
#  save the output patches objects for legend making
patches0 = [ plt.plot([],[], marker=markers[i], ms=8, ls="", mec=None, color=colors[i], 
          label="{:s}".format(texts[i]) )[0]
          for i in range(len0) ]
# Plot point data
# Demo data is used here
for i in range(len1):
    plt.plot(xs[i], ys[i], marker=markers1[i], ms=sizes1[i], color=colors1[i])

# Plot legend in the upper-right corner
plt.legend(handles=patches0, bbox_to_anchor=(1, 1), title="Potveg", 
                   loc='upper right', ncol=1, facecolor="lightgray", numpoints=1 )
plt.show()

plot1

Edit1

Since the data has categories and quantities information to render on the plot, my answer is not complete without handling both of them.

The code to produce 2 legends on a single plot is not straight forward as one may think.

import matplotlib.pyplot as plt

# For `Categories` symbol
# ----------------
# Each item of legends requires 3 propereties: color/label_text/marker_shape
color_V = ["green", "orange", "purple", "red", "lightgreen", "gray"]
text_V = ["4", "9", "13", "15", "19", "33"]
marker_V = ["o", "o", "o", "o", "o", "o"]
len_V = len(color_V)

# For `Size/quantities` symbol
# --------------------
color_S = ["gray", "gray", "gray", "gray"]
sizes_S = [4, 8, 12, 16]         #increasing values ...
text_S = ["4", "8", "12", "16"]  # cover `sizes1` below
marker_S = ["o", "o", "o", "o"]  #use disk shape
len_S = len(color_S)

# Data locations and attributes
xs = [3,2,4,5,4,2,7,3]
ys = [41,12,32,15,35,21,23,43]
colors1 = ["green", "orange", "purple", "red", "lightgreen", "gray", "green", "orange"]
texts1 = ["4", "9", "13", "15", "19", "33", "4", "9"]
markers1 = ["o", "o", "o", "o", "o", "o", "o", "o"]
sizes1 = [8,16,9,12,7,4,10,6]
len1 = len(xs)

# Plot `none` data point and 
#  save the output patches objects for legend making
patches_V = [ plt.plot([],[], marker=marker_V[i], ms=8, ls="", color=color_V[i], 
          label="{:s}".format(text_V[i]) )[0] 
          for i in range(len_V) ]

# Do it again for another legend
patches_S = [ plt.plot([],[], marker=marker_S[i], ms=sizes_S[i], ls="", 
        color=color_S[i], 
        label="{:s}".format(text_S[i]) )[0] for i in range(len_S) ]

# Plot point data
# Demo data is used here
for i in range(len1):
    plt.plot(xs[i], ys[i], marker=markers1[i], ms=sizes1[i], color=colors1[i])

# Plot 1st legend in the upper-right corner
first_legend = plt.legend(handles=patches_V, bbox_to_anchor=(1, 1), title="Categories", 
                   loc='upper right', ncol=1, facecolor="lightgray", numpoints=1 )

# Need to freeze first legend to enable addition of the second legend by ...
# Add the legend manually to the current Axes
plt.gca().add_artist(first_legend)

# Then we can add the second legend normally
plt.legend(handles=patches_S, bbox_to_anchor=(0, 1), title="Sizes", 
                   loc='upper left', ncol=1, facecolor="lightgray", numpoints=1 )


plt.show()

twolegend

Answered By: swatchai