How to create two legend objects for a single plot

2019-07-09 22:37发布

问题:

I use the following example code to generate a bar plot.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 5, 5)
y = np.exp(x)
w = x[1] - x[0]

colors = ['blue' if idx % 2 == 0 else 'red' for idx in range(len(x))]

fig, ax = plt.subplots()
ax.bar(x, y, width=w, color=colors, label='sample plot')
ax.legend()
plt.show()
plt.close(fig)

I would like to show both the red and blue colors in the legend object. I can think of 2 visually appealing ideas. The first idea is to create two rectangle objects (one red, the other blue) that are vertically centered about the legend label. The second idea is to overlay half of a rectangle (in red) over the legend object (in blue). But I do not know how to accomplish either of these. I have looked at the matplotlib docs, I'm just confused. How can I go about doing this?

回答1:

I guess an easy option is to use a matplotlib.legend_handler.HandlerTuple and supply a tuple of a red and blue rectangle to the legend handles.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.legend_handler

x = np.linspace(0, 5, 5)
y = np.exp(x)
w = x[1] - x[0]

colors = ['blue' if idx % 2 == 0 else 'red' for idx in range(len(x))]

fig, ax = plt.subplots()
bars = ax.bar(x, y, width=w, color=colors, label='sample plot')

ax.legend(handles = [tuple(bars[:2])], labels=['sample plot'], loc='upper left', 
          handler_map = {tuple: matplotlib.legend_handler.HandlerTuple(None)})

plt.show()

Else, you can of course use any custom handler you like as described in the legend guide.