Show only certain items in legend
Asked Answered
T

6

116

I currently am plotting a stacked bar graph of a large amount of taxonomic data, and only wish to show significant species in the legend (out of ~500 I wish to show ~25). Is there a simple way to do this? Below is the code I have:

labels=['0','20','40','60','80','100','120']
ax1=subj1df.plot(kind='barh', stacked=True,legend=True,cmap='Paired', grid=False)
legend(ncol=2,loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0.)
label1=['Baseline','8h','24h','48h','96h','120h']
ax1.set_yticklabels(label1, fontdict=None, minor=False)
plt.title('Subject 1 Phyla',fontweight='bold')
plt.savefig('Subject1Phyla.eps', format='eps', dpi=1000)
ax1.set_xticklabels(labels)

Edit: tried adding this to show only one legend entry, however only returns an empty legend:

h, l = ax1.get_legend_handles_labels()
legend(l[4],h[4],ncol=2,loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0.)
Thordia answered 10/7, 2014 at 15:50 Comment(0)
A
40

I often insert an empty label for legends I don't want to show. I made an extremely simple example which I hope will help you. You will need to tweak this to your own data but the elements you need should be there.

import matplotlib.pyplot as plt 
import numpy as np

myY=np.random.randint(20, size=10)
myX=np.arange(0,len(myY))

selected=[5,10,15]

fig = plt.figure()
for X,Y in zip(myX,myY):
    if Y in selected:
        mylabel="label = %s"%(Y); mycolor='blue'
    else:
        mylabel=None; mycolor='red'
    plt.scatter(X,Y,50, color=mycolor, label=mylabel)
plt.legend()
plt.show()

This creates the following plot: enter image description here

Assuming answered 10/7, 2014 at 17:57 Comment(5)
legend also takes a list of artists and a list of labels to precisely control what goes into your legendBandy
This could work, but is there a way for selected to be a list of strings of the legend entries I want? my plot is a stacked bar plot of many entries.Thordia
Sure. For each of your entries (identified by X,Y, and name) check whether your current entry is in a list of selected labels that you want to show the legend for. Its difficult to show you how to do this unless you show more info as to how your data looks.Assuming
Try the indicated solution with label='nolegend'Musa
Philipp means label='_nolegend_' (note the underscores), see the answer from jlansey.Superincumbent
A
298

This works:

plt.plot(x, y, label='_nolegend_')

source

Algology answered 29/2, 2016 at 22:22 Comment(10)
Hmm. Tough luck to the poor bastard who wants his label to say _nolegend_.Pinta
Is there any reason the developers chose this over label=None ?Comminute
Everything that starts with _ is skipped from the legend.Zennas
How can I label my plot as _nolegend_ ? :PGalahad
as shown, by adding the parameter: label='_nolegend_'Algology
I'm plotting data from multiple columns of a dataframe on the same chart. Your solution doesn't work if I implement it as df.plot(..., label='nolegend'). It works if I rename the dataframe columns as 'nolegend' before running df.plot(...) but I get the following warning, repeated for each column I'm plotting: UserWarning: The handle <matplotlib.lines.Line2D object at 0x000001B26EB57370> has a label of 'nolegend' which cannot be automatically added to the legend. ax.legend(handles, labels, loc="best", title=title) Is there a way to avoid that warning?Weatherworn
you are missing an underscoreAlgology
Thank you for your response. I meant _nolegend but the editor here automatically removed the underscores and converted the text in between to italics. Anyway, as I said, your solution with the underscore works but gives me the warnings. Have you come across them? Not sure why I get them.Weatherworn
Link doesn't work anymore :(Ashlynashman
Unfortunately, I noticed today that it now says MatplotlibDeprecationWarning: An artist whose label starts with an underscore was passed to legend(); such artists will no longer be ignored in the future. for this solution. The use of None seems to be the best solution.Breaststroke
A
40

I often insert an empty label for legends I don't want to show. I made an extremely simple example which I hope will help you. You will need to tweak this to your own data but the elements you need should be there.

import matplotlib.pyplot as plt 
import numpy as np

myY=np.random.randint(20, size=10)
myX=np.arange(0,len(myY))

selected=[5,10,15]

fig = plt.figure()
for X,Y in zip(myX,myY):
    if Y in selected:
        mylabel="label = %s"%(Y); mycolor='blue'
    else:
        mylabel=None; mycolor='red'
    plt.scatter(X,Y,50, color=mycolor, label=mylabel)
plt.legend()
plt.show()

This creates the following plot: enter image description here

Assuming answered 10/7, 2014 at 17:57 Comment(5)
legend also takes a list of artists and a list of labels to precisely control what goes into your legendBandy
This could work, but is there a way for selected to be a list of strings of the legend entries I want? my plot is a stacked bar plot of many entries.Thordia
Sure. For each of your entries (identified by X,Y, and name) check whether your current entry is in a list of selected labels that you want to show the legend for. Its difficult to show you how to do this unless you show more info as to how your data looks.Assuming
Try the indicated solution with label='nolegend'Musa
Philipp means label='_nolegend_' (note the underscores), see the answer from jlansey.Superincumbent
M
14

For whatever reason both answers didn't work for mine situation. What worked, and actually was indicated above:

legend also takes a list of artists and a list of labels to precisely control what goes into your legend – tacaswell Jul 11 '14 at 4:46

import pandas as pd
import matplotlib.pyplot as plt
import pylab

pd.Series(range(10)).plot(color = 'grey')
x = list(range(10))
y = [i + 1 for i in x]  
scat1 = plt.scatter(x, y)

pylab.legend([scat1],['moved points'], loc = 'upper left')

plt.show()

The result of the code: The result of the code:

Mauro answered 19/3, 2017 at 18:0 Comment(1)
Clean solution that scales properly, thank you for sharingLaunceston
C
7

You can also use an empty string variable:

    plt.plot(xData, yData, ..., label=str())

By passing an empty str() object, it doesn't write down anything.

Matplotlib API reference

Cynthea answered 30/1, 2019 at 12:46 Comment(1)
or save yourself 3 characters and write label=""Wigeon
F
2

I know this post is coming up on a decade old, but I was looking for a way to do something similar and this post was on top of the google results. I was working with data tracking heap usage of a process and the processes that it spawned. Most of the processes used up a negligible amount of memory, and displaying the entire legend would have been unwieldy. I ended up with the following solution:

label_names = heap_df.columns.values.tolist()
max_per_proc = heap_df.max()
max_heap_overall = max(max_per_proc)

fig, ax = plt.subplots()
plt.stackplot(heap_df.index, heap_df.values.T, labels=label_names)
lines, labels = ax.get_legend_handles_labels()
lbl_idx = []
for idx in range(len(labels)):
    if max_per_proc[labels[idx]] / max_heap_overall > 0.01:
        lbl_idx.append(idx)
ax.legend([lines[i] for i in lbl_idx], [labels[i] for i in lbl_idx])
        
plt.show()
Ferous answered 22/6, 2022 at 17:50 Comment(0)
B
0

In the case where you are plotting multiple lines simultaneously with a Pandas dataframe and the Pandas plot method, it's not as easy to control which lines make it onto the legend.

Here is a solution to this problem:

df_line_data.plot(legend=False)

labels = [(col if col in cols_to_plot else '_Hidden label') for col in df_line_data.columns]

ax.legend(labels=labels)
Breaststroke answered 20/12, 2023 at 2:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.