Home > Net >  How to ignore some labels in subplots legend?
How to ignore some labels in subplots legend?

Time:03-05

I have a figure with subplots I created with data from a panda data frame:

    # Definition of the dataframe

df = pd.DataFrame({'Colors': {0: 'Red', 1: 'Blue', 2: 'Green', 3: 'Blue', 4: 'Red'}, 'X_values': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}, 'Y_values': {0: 2, 1: 4, 2: 8, 3: 10, 4: 4}, 'MinY_values': {0: 1.5, 1: 3, 2: 7.5, 3: 8, 4: 2}, 'MaxY_values': {0: 2.5, 1: 5, 2: 9.5, 3: 11, 4: 6}})

I defined two lists which contain the color for each point on the figure as well as the label I want to assign to each point (Then, I can change a label for a given point if needed):

color
Out[8]: ['red', 'blue', 'green', 'blue', 'red']

labels
Out[9]: 
['It is a red point',
 'What a wonderful blue point',
 'Sounds to be a green point',
 'What a wonderful blue point',
 'It is a red point']
 

On each subfigure, I need to add an horizontal line.

Here is my problem: When I add a legend to the figure, the label is repeated if the color is repeated and the horizontal line is included in the legend which will "shift" the legend.

How can I ignore the repeated colors in the legend as well as not include the black line in it ?

Plot

Here is my code:

import pandas as pd

from matplotlib.pyplot import show, subplots


# Definition of the dataframe

df = pd.DataFrame({'Colors': {0: 'Red', 1: 'Blue', 2: 'Green', 3: 'Blue', 4: 'Red'}, 'X_values': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}, 'Y_values': {0: 2, 1: 4, 2: 8, 3: 10, 4: 4}, 'MinY_values': {0: 1.5, 1: 3, 2: 7.5, 3: 8, 4: 2}, 'MaxY_values': {0: 2.5, 1: 5, 2: 9.5, 3: 11, 4: 6}})


# Definition of the different colors and labels

color = []

labels = []
 

for i in df['Colors']:
    if i == 'Red':
        color.append('red')
        labels.append('It is a red point')
    if i == 'Blue':
        color.append('blue')
        labels.append('What a wonderful blue point')
    if i == 'Green':
        color.append('green')
        labels.append('Sounds to be a green point')
 
# Figure

fig,axes = subplots(3,1,sharex = True)

fig.subplots_adjust(top=0.975,
bottom=0.07,
left=0.05,
right=0.585,
hspace=0.0,
wspace=0.2) 

for x_val,y_val,min_val,max_val,colors in zip(df['X_values'],df['Y_values'],df['MinY_values'],df['MaxY_values'],color):
    axes[0].errorbar(x_val,y_val,yerr = [[min_val],[max_val]] ,color = colors,barsabove='True',fmt = 'o')

axes[0].axhline(y=5, color='black', linestyle='--')
    
for x_val,y_val,min_val,max_val,colors in zip(df['X_values'],df['Y_values'],df['MinY_values'],df['MaxY_values'],color):
    axes[1].errorbar(x_val,y_val,yerr = [[min_val],[max_val]] ,color = colors,barsabove='True',fmt = 'o')

axes[1].axhline(y=5, color='black', linestyle='--')
    
for x_val,y_val,min_val,max_val,colors in zip(df['X_values'],df['Y_values'],df['MinY_values'],df['MaxY_values'],color):
    axes[2].errorbar(x_val,y_val,yerr = [[min_val],[max_val]] ,color = colors,barsabove='True',fmt = 'o',label = labels)

axes[2].axhline(y=5, color='black', linestyle='--')


# Legend

fig.legend(labels)

fig.legend(bbox_to_anchor=(2,2), loc='center', ncol=1)
  
show()

CodePudding user response:

In this case, the easiest is to create a custom legend.

Some notes:

  • plt.tight_layout() can be used to fit the legend and the labels nicely into the plot; this is much more flexible than fig.subplots_adjust(), especially when later changes are made to the plots
  • fig.legend() uses the "current ax" (current subplot), which in this case is axes[2]
  • when putting the legend to the right of the plots, it helps to use loc='upper left' for the anchor point; 'loc' values that aren't at the left are too hard to control (bbox_to_anchor sets the position of the anchor point, measured in custom legend

  • Related