leg.legendHandles 和 ax.get_legend_handles_labels() 之间的 1-1 映射可以实现这一点,可以做到吗?
是的,看下面的例子
import matplotlib.pyplot as plt
figure, (axes1, axes2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
orange = axes1.errorbar([1, 2, 3], [1, 1, 1], yerr=[.1, .1, .1], c='orange', label='orange')
axes1.legend()
axes1.plot([1, 2, 3], [2, 2, 2], c='blue', label='blue')
handles, labels = axes1.get_legend_handles_labels()
axes2.legend([handles[1]], [labels[1]])
plt.show()
您还可以创建返回 matplotlib.pyplot.plot() 的图例。
import matplotlib.pyplot as plt
figure, (axes1, axes2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
orange = axes1.errorbar([1, 2, 3], [1, 1, 1], yerr=[.1, .1, .1], c='orange', label='orange')
axes1.legend()
axes1.plot([1, 2, 3], [2, 2, 2], c='blue', label='blue')
axes2.legend([orange], ['orange'])
plt.show()
现在,如果给了我leg,我怎么能重现传奇?
我试过了
ax.legend(leg.legendHandles, [i.get_text() for i in leg.get_texts()])
我在sourcecode of legend 中找到的与句柄相关的属性也是legendHandles。该属性在_init_legend_box() 中初始化。相关代码是
def _init_legend_box(self, handles, labels, markerfirst=True):
...
text_list = [] # the list of text instances
handle_list = [] # the list of text instances <-- I think this might be typo
handles_and_labels = []
...
for orig_handle, lab in zip(handles, labels):
handler = self.get_legend_handler(legend_handler_map, orig_handle)
if handler is None:
_api.warn_external(
"Legend does not support {!r} instances.\nA proxy artist "
"may be used instead.\nSee: "
"https://matplotlib.org/users/legend_guide.html"
"#creating-artists-specifically-for-adding-to-the-legend-"
"aka-proxy-artists".format(orig_handle))
# We don't have a handle for this artist, so we just defer
# to None.
handle_list.append(None)
else:
textbox = TextArea(lab, textprops=label_prop,
multilinebaseline=True)
handlebox = DrawingArea(width=self.handlelength * fontsize,
height=height,
xdescent=0., ydescent=descent)
text_list.append(textbox._text)
# Create the artist for the legend which represents the
# original artist/handle.
handle_list.append(handler.legend_artist(self, orig_handle,
fontsize, handlebox))
handles_and_labels.append((handlebox, textbox))
...
self.texts = text_list
self.legendHandles = handle_list
正如我们所见,handle_list 最终分配给了self.legendHandles。在for循环中将值附加到handle_list,如下所示
# Create the artist for the legend which represents the
# original artist/handle.
handle_list.append(handler.legend_artist(self, orig_handle,
fontsize, handlebox))
# print(f'{orig_handle} - {type(orig_handle}') gives
"""
<ErrorbarContainer object of 3 artists> - <class 'matplotlib.container.ErrorbarContainer'>
"""
评论说Create the artist for the legend which represents the original artist/handle。但是从下面的例子中,我们可以看到返回的艺术家并不代表原始的句柄。我认为这可能是 matplotlib 的一个错误。
import matplotlib.pyplot as plt
figure, (axes1, axes2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))
orange = axes1.errorbar([1, 2, 3], [1, 1, 1], yerr=[.1, .1, .1], c='orange', label='orange')
axes1.legend()
axes1.plot([1, 2, 3], [2, 2, 2], c='blue', label='blue')
leg = axes1.get_legend()
handles, labels = axes1.get_legend_handles_labels()
print(f'{orange} - {type(orange)}')
print(f'{handles[1]} - {type(handles[1])}')
print(f'{leg.legendHandles} - {type(leg.legendHandles)}')
"""
<ErrorbarContainer object of 3 artists> - <class 'matplotlib.container.ErrorbarContainer'>
<ErrorbarContainer object of 3 artists> - <class 'matplotlib.container.ErrorbarContainer'>
[<matplotlib.collections.LineCollection object at 0x7f4c79919040>] - <class 'list'>
"""