在单独的图上绘制图例时出错

Posted

技术标签:

【中文标题】在单独的图上绘制图例时出错【英文标题】:Error when drawing a legend on a separate plot 【发布时间】:2021-01-20 08:50:03 【问题描述】:

我想在与原始图不同的框架上绘制图例。我可以从绘图命令中绘制图例。但不是来自 fill_between 的传说。

这是一个示例代码

#!/usr/bin/env python

import numpy as np
import matplotlib.pyplot as plt

xx = np.linspace(0, 3.14*3, 100)
yy = np.sin (xx)
zz = yy +0.5

# I can draw a plot with legend
fig = plt.figure( )
ax = fig.add_subplot(1, 1, 1,)

line1, = ax.plot (xx, yy, label='xx')
line2, = ax.plot (xx, zz, label='yy')

fill0 = ax.fill_between (xx, yy, zz, label='filling', alpha=0.2, color='grey' ) 

ax.legend ( handles=[line1, line2, fill0])
plt.show()

# I can draw a empty plot with the legend of the lines 
plt.legend(handles=[line1, line2])
plt.show()

# I can't draw an empty plot with the legend of the fill
# Why ?
# Can I fix this ?

plt.legend(handles=[fill0,])
plt.show()

现在是错误:

 Traceback (most recent call last):
 File "Untitled.py", line 34, in <module>
 plt.legend(handles=[fill0,])
 File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/pyplot.py", line 2721, in legend 
return gca().legend(*args, **kwargs)
 File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/axes/_axes.py", line 417, in legend
self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/legend.py", line 503, in __init__
self._init_legend_box(handles, labels, markerfirst)
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/legend.py", line 767, in _init_legend_box
fontsize, handlebox))
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/legend_handler.py", line 117, in legend_artist
fontsize, handlebox.get_transform())
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib  /legend_handler.py", line 727, in create_artists
self.update_prop(p, orig_handle, legend)
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/legend_handler.py", line 76, in update_prop
legend._set_artist_props(legend_handle)
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/legend.py",    line 550, in _set_artist_props
a.set_figure(self.figure)
File "/Users/marti/anaconda3/envs/PROD/lib/python3.7/site-packages/matplotlib/artist.py", line 704, in set_figure
raise RuntimeError("Can not put single artist in "
RuntimeError: Can not put single artist in more than one figure

有什么提示可以解决这个问题吗?

【问题讨论】:

你想要 2 个子图吗?就像示例中的here“或者如果你想拥有2个子图”? 不,我需要将图例放在单独的图上,以便将其单独放在 PowerPoint 中。 您可以在新轴之间放置一个填充,然后设置视图限制使其不可见。 是的,我可以在 fill_between 上绘制图例。我将这样做。但我对此并不十分满意:-(( 【参考方案1】:

所涉及的artist 对象具有深层嵌套数据,matplotlib 选择不允许其在其他轴上重复使用。解决方法代码可以是这样的:

(这里只给出接近尾声的相关代码)

# if want to plot the filled patch, must create anew
grey_patch1 = mpatches.Patch(label='filling1', alpha=0.2, color='grey')
plt.legend(handles=[line1, line2, grey_patch1])
plt.show()

#grey_patch1 can be reused, no need to recreate like this
grey_patch2 = mpatches.Patch(label='filling2', alpha=0.2, color='red')
plt.legend(handles=[grey_patch1, grey_patch2,])

plt.show()

以上代码需要import matplotlib.patches as mpatches

【讨论】:

好的,用相同的颜色、alpha 等重新创建一个新的但更简单的对象......是一个很好的解决方法。谢谢你的想法,我会用的。无论如何,我仍然觉得这是一种解决方法,它不应该附加。奥利维尔 @Marti 实际上它是一种手动方法,可用于解决您在现实生活中会发现的复杂图例制作的所有要求。您已经了解到自动方法有局限性。在您的情况下,fill0(与简单的line1line2 不同)不允许重用,以避免在当前版本的 matplotlib 中出现图形渲染问题。

以上是关于在单独的图上绘制图例时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何绘制这个有很多功能的图的图例?

如何将origin多个图层的图例放到一个图上

R 用户定义的函数保存图形 - dev.off() 出错?

循环时出错:尝试在 vectorIndex 中选择多个元素

如何根据 ggplot2 绘制的图上的 y 轴值覆盖构面标签?

处理和消除 MatLab 图例中的多个条目