Reputation: 275
I am trying to change the color of the legend item to black. I have done something similar in the past with scatter
instead of plot
but since I also want fillstyle
, I need to use plot
.
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import container
def ColorExtractor(cmap, colist):
cmap = matplotlib.cm.get_cmap(cmap)
rbga = cmap(colist)
return rbga
colors = ColorExtractor('Blues', [3/3, 3/3, 2/3, 1/3])
fig, ax = plt.subplots()
x_data = np.array([0.975, 0.75, 0.525])
y_min = np.array([3, 3, 2])
y_max = np.array([4, 4, 3])
for xs, ys, cols, labs, flstl in zip([x_data, x_data], [y_min, y_max], [colors, colors], ['$x_{min}$', '$x_{max}$'], ['bottom', 'top']):
ax.plot(xs, ys, 'k:')
for x, y, col in zip(xs, ys, cols):
ax.plot(x, y, color=col, marker='<', label=labs, fillstyle=flstl, markeredgecolor='k', linestyle='none', markersize=10)
ax.set_xlim(0.5, 1)
ax.set_ylim(1, 5)
ax.set_xlabel('$x$', fontsize=15)
ax.set_ylabel('$y$', fontsize=15)
handles, labels = ax.get_legend_handles_labels()
handles = [i[0] if isinstance(i, container.ErrorbarContainer) else i for i in handles]
by_label = dict(zip(labels, handles))
ax.legend(by_label.values(), by_label.keys(), loc=9, ncol=2, frameon=False)
leg = ax.get_legend()
for i in leg.legendHandles:
i.set_color('k')
i.set_markeredgecolor('k')
#i.set_edgecolor('k')
plt.show()
Everything works fine except the last part which appears to not do anything. So, the color of the legend symbols remains blue instead of black. I also want the edgecolor
to be black but I have commented it because AttributeError: 'Line2D' object has no attribute 'set_edgecolor'
spawns.
EDIT: As @Galunid pointed out, I should probably use set_markeredgecolor
instead set_edgecolor
. However, the main problem is that I want to change the color inside the legend markers to black.
What I am doing wrong?
Upvotes: 0
Views: 1720
Reputation: 80509
If you change the legend handles too soon, also the colors inside the plot will be changed. So, you'll need to make a copy of the handles and then color those copies. Note that set_markerfacecolor()
change the first color of the marker (blue
in the example code). And set_markerfacecoloralt()
would change the second color (the white
). So, probably you'll want set_markerfacecolor('black')
and leave the other color untouched.
Here is an example:
from copy import copy
handles, labels = ax.get_legend_handles_labels()
handles = [copy(i[0]) if isinstance(i, container.ErrorbarContainer) else copy(i) for i in handles]
for i in handles:
i.set_markeredgecolor('black')
i.set_markerfacecolor('crimson') # use 'black' to have that part black
i.set_markerfacecoloralt('gold') # leave this line out in case the second color is already OK
by_label = dict(zip(labels, handles))
ax.legend(by_label.values(), by_label.keys(), loc=9, ncol=2, frameon=False)
Upvotes: 2