J_Scholz
J_Scholz

Reputation: 506

How to obtain a correct legend for a barplot when the first bar is modified?

I have a grouped bar plot where I mark one bar of the plot with a different facecolor depending on a data value (example without group, for simplicity). When I add a legend, it always takes the colors from the first bars. This leads to wrong colors, if the first bar is the "marked bar". I always want it to be the color from the plot-statement, not the changed color.

from matplotlib import pyplot as plt

x = [1,2,3,4]
y = [1,2,3,4]
marked = 0

bars = plt.bar(x, y, color='k',label='label')
bars[marked].set_facecolor('r')
plt.legend()
plt.show()

This leads to a red box in the legend. But I want it to be of the same color as the other bars, which is set dynamically in my real code - in this example: black.

I tried to add:

if marked == 0:
   plt.legend([bars[1]])

But that didn't work as hoped ...

Upvotes: 0

Views: 403

Answers (1)

JohanC
JohanC

Reputation: 80409

A simple solution seems to be to change the order of the statements:

bars = plt.bar(x, y, color='k', label='label')
plt.legend()
bars[marked].set_facecolor('r')

If that wouldn't be possible, the bars can also be relabeled. With bars = plt.bar(..., label='label') the label gets assigned to the bar container element. And when creating the legend, the first bar will be used to decide the color. Note that a label starting with an underscore will be skipped for the legend. So, to have the second bar serve for the color, remove the label of the container (assigning a label starting with underscore), and add its original label to the first bar.

Optionally, to also get the special bar in the legend, it can be assigned an explicit label.

from matplotlib import pyplot as plt

x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
marked = 0

bars = plt.bar(x, y, color='k', label='label')
bars[marked].set_facecolor('r')
if marked == 0:
    bars[1].set_label(bars.get_label())
    bars.set_label('_nolegend_')

bars[marked].set_label('special') # optionally give the special bar an explicit label

plt.legend()
plt.show()

example plot

Upvotes: 1

Related Questions