5

I want to produce a separate legend (e.g. for several subplots sharing similar elements) via

import matplotlib as mpl
import matplotlib.pyplot as plt

plt.legend(handles=[
                mpl.lines.Line2D([0], [0],linestyle='-' ,marker='.',markersize=10,label='example')
            ]
           ,loc='upper left'
           ,bbox_to_anchor=(1, 1)
          )

but I cannot figure out how to add error bars. So, how do I produce a standalone legend with markers and error bars?

For clarity, the legend should look like in the example below, i.e. line with marker + error bar.

import numpy as np
import matplotlib.pyplot as plt

x=np.linspace(0,5,5)
y=x

yerr=np.random.rand(5,1)*5e-1
fig,ax=plt.subplots(nrows=1,ncols=1)
ax.errorbar(x=x,y=y,yerr=yerr,marker='.',ms=10,label='example')

ax.legend(loc='upper left'
          ,bbox_to_anchor=(1, 1)
         )

Edit: A possible workaround is to extract labels and handles from the ax object, i.e. via

import numpy as np
import matplotlib.pyplot as plt

x=np.linspace(0,5,5)
y=x

yerr=np.random.rand(5,1)*5e-1
fig,ax=plt.subplots(nrows=1,ncols=1, constrained_layout=True)
ax.errorbar(x=x,y=y,yerr=yerr,marker='.',ms=10,label='example',legend=None)

handles,labels=ax.get_legend_handles_labels()
fig.legend(handles=handles,labels=labels
           ,loc='upper right'
          )
Stefan
  • 1,697
  • 15
  • 31
  • Maybe check out this post, it could contain an answer: – Richard May 10 '19 at 09:51
  • 1
    With this answer I was able to find a workaround, namely extracting handles and labels from one of the axis and using them to create the legend. I added the workaround as an edit. However it would still be desirable to create a legend from scratch to avoid playing around with numerous handles / labels. – Stefan May 10 '19 at 10:58
  • Maybe https://topanswers.xyz/tex?q=1004#a1198 could be helpful for your beamer problem – samcarter_is_at_topanswers.xyz May 11 '20 at 16:32

1 Answers1

3

Why not take the (one of the) existing errorbar(s) and use it as legend handle?

import numpy as np
import matplotlib.pyplot as plt

x=np.linspace(0,5,5)
y=x

yerr=np.random.rand(5,1)*5e-1
fig,ax=plt.subplots(nrows=1,ncols=1)
err = ax.errorbar(x=x,y=y,yerr=yerr,marker='.',ms=10, label='example')

ax.legend(handles=[err], labels=["my custom label"], 
          loc='upper left' ,bbox_to_anchor=(1, 1)  )

plt.show()

If instead you persist on creating the errorbar legend handle from scratch, this would look as follows.

import numpy as np
import matplotlib.pyplot as plt

x=np.linspace(0,5,5)
y=x

yerr=np.random.rand(5,1)*5e-1
fig,ax=plt.subplots(nrows=1,ncols=1)
ax.errorbar(x=x,y=y,yerr=yerr,marker='.',ms=10, label='example')


from matplotlib.container import ErrorbarContainer
from matplotlib.lines import Line2D
from matplotlib.collections import LineCollection
line = Line2D([],[], ls="none")
barline = LineCollection(np.empty((2,2,2)))
err = ErrorbarContainer((line, [line], [barline]), has_xerr=True, has_yerr=True)

ax.legend(handles=[err], labels=["my custom label"], 
          loc='upper left' ,bbox_to_anchor=(1, 1)  )

plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • This is essentially the workaround I used (see my edit). This can however get quite messy if there are several different subplots with various traces filled via a loop. – Stefan May 10 '19 at 11:30
  • Is the aim to get a legend with *one* errorbar in it? Then you will just need to make *one* of the errorbars in the loop available as `err`. Else I might not understand the problem. – ImportanceOfBeingErnest May 10 '19 at 11:33
  • Imagine I have several subplots, all with different traces (some with error bars some without). Some subplots might also be of different type, e.g. a histogram. Some information might therefore be redundant and is not required in the legend. Therefore it would be nice to simply build the legend from scratch without worrying about the various handles and labels at all. – Stefan May 10 '19 at 12:37
  • Ok, I updated the answer. But it's sure much more complicated than just assigning the output of one of the errorbars that appear somewhere in your figure to a variable and use it afterwards. – ImportanceOfBeingErnest May 10 '19 at 13:30
  • Perfect, thanks! Exactly what I was looking for. As already mentioned, sometimes creating the legend from scratch is preferable, especially when the plot is consisting of several subplots. For easy plots (as in the example I have given) it is of course the better approach to just get the label and handle from the axis. – Stefan May 11 '19 at 10:01
  • Hi @ImportanceOfBeingErnest! I'm doing similar project, I want to know how to add text with errorbar values. Thanks – Megan Jun 07 '22 at 10:13