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')
CodePudding user response:
- This is more easily done by reshaping the dataframe into a long form with
import matplotlib.pyplot as plt # create a matplotlib figure fig, ax = plt.subplots(1, 1, figsize=(10, 6)) # create an axes-level plot sns.scatterplot(data=im, x='Sample', y='Value', hue='Species', style='Feature', ax=ax) ax.spines[['top', 'right']].set_visible(False) sns.move_legend(ax, bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)
CodePudding user response:
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 usematplotlib.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')