Adding second legend to scatter plot

10,684

Solution 1

You will need to create the second legend yourself, i.e. you need to create some artists to populate the legend with. In the case of a scatter we can use a normal plot and set the marker accordingly. This is shown in the below example. To actually add a second legend we need to add the first legend to the axes, such that the new legend does not overwrite the first one.

import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np; np.random.seed(1)
import pandas as pd
plt.rcParams["figure.subplot.right"] = 0.8
v = np.random.rand(30,4)
v[:,2] = np.random.choice(np.arange(1980,2015,5), size=30)
v[:,3] = np.random.randint(5,13,size=30)

df= pd.DataFrame(v, columns=["x","y","year","quality"])
df.year = df.year.values.astype(int)
fig, ax = plt.subplots()
for i, (name, dff) in enumerate(df.groupby("year")):
    c = matplotlib.colors.to_hex(plt.cm.jet(i/7.))
    dff.plot(kind='scatter',x='x',y='y', label=name, c=c, 
             s=dff.quality**2, ax=ax)

leg = plt.legend(loc=(1.03,0), title="Year")
ax.add_artist(leg)
h = [plt.plot([],[], color="gray", marker="o", ms=i, ls="")[0] for i in range(5,13)]
plt.legend(handles=h, labels=range(5,13),loc=(1.03,0.5), title="Quality")
plt.show()

enter image description here

Solution 2

Have a look at http://matplotlib.org/users/legend_guide.html.

It shows how to have multiple legends (about halfway down) and there is another example that shows how to set the marker size.

If that doesn't work, then you can also create a custom legend (last example).

Share:
10,684
Newstudent14
Author by

Newstudent14

Updated on July 18, 2022

Comments

  • Newstudent14
    Newstudent14 almost 2 years

    Is there a way to add a secondary legend to a scatterplot, where the size of the scatter is proportional to some data?

    I have written the following code that generates a scatterplot. The color of the scatter represents the year (and is taken from a user-defined df) while the size of the scatter represents variable 3 (also taken from a df but is raw data):

    import pandas as pd 
    
    colors = pd.DataFrame({'1985':'red','1990':'b','1995':'k','2000':'g','2005':'m','2010':'y'}, index=[0,1,2,3,4,5])
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    for i in df.keys():
        df[i].plot(kind='scatter',x='variable1',y='variable2',ax=ax,label=i,s=df[i]['variable3']/100, c=colors[i])
    
    ax.legend(loc='upper right')
    ax.set_xlabel("Variable 1")
    ax.set_ylabel("Variable 2")
    

    This code (with my data) produces the following graph:

    Representative figure with single legend

    So while the colors/years are well and clearly defined, the size of the scatter is not.

    How can I add a secondary or additional legend that defines what the size of the scatter means?