I would like to plot two features in the same plot. My problem is with the legend. I would like to have one legend for colors(species) and one for the marker (Label defined by me). And I don't need to repeat the colors in the legend, as is happening in this example.
this is what I'm trying:
import seaborn as sns
import matplotlib.pyplot as plt
import random
import matplotlib.colors as mcolors
random.seed(5)
iris = sns.load_dataset("iris")
species_list = list(iris.species.unique())
colors_name = list(mcolors.CSS4_COLORS.keys())
color_species = random.sample(colors_name,len(species_list))
fig,ax = plt.subplots(1,1,figsize=(10,6))
sns.scatterplot(data=iris,edgecolor="black", x=iris.index.values, y='sepal_length',s=50,alpha=0.8, hue='species',palette=color_species,ax=ax,label='Feat. 1')
sns.scatterplot(data=iris,edgecolor="black",marker='*', x=iris.index.values, y='sepal_width',s=90,alpha=0.8, hue='species',palette=color_species,ax=ax, label='Feat. 2')
ax.legend(loc='upper right',bbox_to_anchor=(1.5,1))
ax.set_xlabel('Sample')
ax.set_ylabel('Feature 1 and 2')
To manipulate the legend, you need to get the legend handles using get_legend_handles_labels()
, then pick half the entries (3 in your case) and plot them as a legend. Then use matplotlib.lines
to create the kind of icon you need (color, shape, etc.) and pass that as the handles for second legend along with the label text you want. You can use title to add titles to the legends. The code is shown below. Hope this is what you are looking for.
import seaborn as sns
import matplotlib.pyplot as plt
import random
import matplotlib.colors as mcolors
random.seed(5)
iris = sns.load_dataset("iris")
species_list = list(iris.species.unique())
colors_name = list(mcolors.CSS4_COLORS.keys())
color_species = random.sample(colors_name,len(species_list))
fig,ax = plt.subplots(1,1,figsize=(10,6))
sns.scatterplot(data=iris,edgecolor="black", x=iris.index.values, y='sepal_length',s=50,alpha=0.8, hue='species',
palette=color_species,ax=ax)#,label='Feat. 1')
sns.scatterplot(data=iris,edgecolor="black",marker='*', x=iris.index.values, y='sepal_width',s=90,alpha=0.8,
hue='species',palette=color_species,ax=ax)#, label='Feat. 2')
h,l = ax.get_legend_handles_labels() ##Get the legend handles and lables
l1 = ax.legend(h[:int(len(h)/2)],l[:int(len(l)/2)], loc='upper right',bbox_to_anchor=(1.2,1), title='Title 1') ##Plot half as the first legend
from matplotlib.lines import Line2D
myHandle = [Line2D([], [], marker='.', color='red', markersize=10, linestyle='None'),
Line2D([], [], marker='*', color='blue', markersize=10, linestyle='None')] ##Create custom handles for 2nd legend
l2 = ax.legend(handles=myHandle, labels = ['MyLabel1', 'MyLabel2'], loc='upper right',bbox_to_anchor=(1.2,0.8), title='Title 2') ##Add 2nd legend
ax.add_artist(l1) # 2nd legend will erases the first, so need to add it
ax.set_xlabel('Sample')
ax.set_ylabel('Feature 1 and 2')