Combined legend entry for plot and fill_between
Asked Answered
F

2

19

This is similar to Matlab: Combine the legends of shaded error and solid line mean, except for Matplotlib. Example code:

import numpy as np
import matplotlib.pyplot as plt

x = np.array([0,1])
y = x + 1
f,a = plt.subplots()
a.fill_between(x,y+0.5,y-0.5,alpha=0.5,color='b')
a.plot(x,y,color='b',label='Stuff',linewidth=3)
a.legend()

plt.show()

The above code produces a legend that looks like this:

enter image description here

How can I create a legend entry that combines the shading from fill_between and the line from plot, so that it looks something like this (mockup made in Gimp):

enter image description here

Freeholder answered 6/10, 2014 at 13:48 Comment(0)
D
25

MPL supports tuple inputs to legend so that you can create composite legend entries (see the last figure on this page). However, as of now PolyCollections--which fill_between creates/returns--are not supported by legend, so simply supplying a PolyCollection as an entry in a tuple to legend won't work (a fix is anticipated for mpl 1.5.x).

Until the fix arrives I would recommend using a proxy artist in conjunction with the 'tuple' legend entry functionality. You could use the mpl.patches.Patch interface (as demonstrated on the proxy artist page) or you could just use fill. e.g.:

import numpy as np
import matplotlib.pyplot as plt

x = np.array([0, 1])
y = x + 1
f, a = plt.subplots()
a.fill_between(x, y + 0.5, y - 0.5, alpha=0.5, color='b')
p1 = a.plot(x, y, color='b', linewidth=3)
p2 = a.fill(np.NaN, np.NaN, 'b', alpha=0.5)
a.legend([(p2[0], p1[0]), ], ['Stuff'])

plt.show()

Compound legend with fill_between

Dossier answered 6/10, 2014 at 17:42 Comment(1)
Thanks! Adding linewidth=0 to the fill makes this good enough, that removes the 'frame' from the legend entry. If you happen to know how to make the legend keys the same length, so the line from plot extends to the left/right edges of the fill rectangle in the legend, that would be even better.Connel
Y
0

Here is an example using patches. I use get_facecolor() to get the color of fill_between() plot and use it to draw a patch. It is easier to customize.

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

x = np.array([0, 1])
y = x + 1
fig, ax = plt.subplots()

p0 = ax.fill_between(x, y + 0.5, y - 0.5, alpha=0.5, color='b')
p1 = ax.plot(x, y, color='b', linewidth=3, label ='abc')

patch = mpatches.Patch(color= p0.get_facecolor(),linewidth=0)
red_patch = mpatches.Patch(color= 'r',linewidth=0)


fig.legend(handles = [( patch,p1[0]), red_patch], labels = [p1[0].get_label(),'b'],  handleheight = 2)
plt.show()

enter image description here

Yellowwood answered 5/8, 2024 at 16:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.