118

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.)
0

6 Answers 6

300

This works:

plt.plot([0, 4], [3,4])
plt.plot([0, 4], [2,3],label='_nolegend_') # element missing from legend
plt.plot([0, 4], [1,2])
plt.legend(['first', 'third'])

enter image description here

11
  • 57
    Hmm. Tough luck to the poor bastard who wants his label to say _nolegend_.
    – Jason S
    Commented Jan 6, 2019 at 16:26
  • 17
    Is there any reason the developers chose this over label=None ?
    – rovyko
    Commented Apr 16, 2019 at 22:44
  • 35
    Everything that starts with _ is skipped from the legend.
    – StSav012
    Commented May 15, 2019 at 17:21
  • How can I label my plot as _nolegend_ ? :P Commented Jun 19, 2020 at 10:46
  • 1
    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?
    – ric
    Commented Nov 28, 2022 at 17:37
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

5
  • 8
    legend also takes a list of artists and a list of labels to precisely control what goes into your legend
    – tacaswell
    Commented Jul 11, 2014 at 4:46
  • 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.
    – Funsaized
    Commented Jul 11, 2014 at 14:10
  • 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. Commented Jul 11, 2014 at 15:50
  • Try the indicated solution with label='nolegend' Commented Oct 7, 2016 at 23:13
  • 10
    Philipp means label='_nolegend_' (note the underscores), see the answer from jlansey. Commented Aug 23, 2018 at 19:23
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:

1
  • Clean solution that scales properly, thank you for sharing
    – jlandercy
    Commented Apr 19, 2020 at 5:09
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

1
  • 4
    or save yourself 3 characters and write label=""
    – MaxS
    Commented Jun 27, 2019 at 16:04
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()
1

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)

Not the answer you're looking for? Browse other questions tagged or ask your own question.