Python 显示pyplot图形后隐藏线
我正在使用pyplot显示最多30行的折线图。我想添加一种方法来快速显示和隐藏图形上的各条线。Pyplot确实有一个菜单,您可以在其中编辑线属性以更改颜色或样式,但当您想要隐藏线以隔离感兴趣的线时,该菜单相当笨拙。理想情况下,我希望使用图例上的复选框来显示和隐藏线条。与在图像编辑器(如Paint.Net)中显示和隐藏层类似,我不确定pyplot是否可以实现这一点,因此我对其他模块持开放态度,只要它们易于分发 如果您愿意,可以将回调连接到图例,在单击图例时显示/隐藏线条。这里有一个简单的例子: 这里有一个更有趣的例子,它不需要手动指定线条之间的关系,图例标记还有一些其他特性 2019年8月更新版本,作为对关于该系统无法正常工作的重复报告的回应;现在应该是了!有关旧版本,请参见 这允许您单击图例项以打开/关闭其对应的艺术家。例如,您可以这样做: 为此:Python 显示pyplot图形后隐藏线,python,matplotlib,Python,Matplotlib,我正在使用pyplot显示最多30行的折线图。我想添加一种方法来快速显示和隐藏图形上的各条线。Pyplot确实有一个菜单,您可以在其中编辑线属性以更改颜色或样式,但当您想要隐藏线以隔离感兴趣的线时,该菜单相当笨拙。理想情况下,我希望使用图例上的复选框来显示和隐藏线条。与在图像编辑器(如Paint.Net)中显示和隐藏层类似,我不确定pyplot是否可以实现这一点,因此我对其他模块持开放态度,只要它们易于分发 如果您愿意,可以将回调连接到图例,在单击图例时显示/隐藏线条。这里有一个简单的例子: 这
谢谢你的帖子!我扩展了上面的类,这样它就可以处理多个图例-例如,如果您使用子图。我在这里分享它,因为我在其他地方找不到任何其他的例子。。。这对其他人来说可能很方便
class InteractiveLegend(object):
def __init__(self):
self.legends = []
self.figures = []
self.lookup_artists = []
self.lookup_handles = []
self.host = socket.gethostname()
def add_legends(self, legend):
self.legends.append(legend)
def init_legends(self):
for legend in self.legends:
self.figures.append(legend.axes.figure)
lookup_artist, lookup_handle = self._build_lookups(legend)
#print("init", type(lookup))
self.lookup_artists.append(lookup_artist)
self.lookup_handles.append(lookup_handle)
self._setup_connections()
self.update()
def _setup_connections(self):
for legend in self.legends:
for artist in legend.texts + legend.legendHandles:
artist.set_picker(10) # 10 points tolerance
for figs in self.figures:
figs.canvas.mpl_connect('pick_event', self.on_pick)
figs.canvas.mpl_connect('button_press_event', self.on_click)
def _build_lookups(self, legend):
labels = [t.get_text() for t in legend.texts]
handles = legend.legendHandles
label2handle = dict(zip(labels, handles))
handle2text = dict(zip(handles, legend.texts))
lookup_artist = {}
lookup_handle = {}
for artist in legend.axes.get_children():
if artist.get_label() in labels:
handle = label2handle[artist.get_label()]
lookup_handle[artist] = handle
lookup_artist[handle] = artist
lookup_artist[handle2text[handle]] = artist
lookup_handle.update(zip(handles, handles))
lookup_handle.update(zip(legend.texts, handles))
#print("build", type(lookup_handle))
return lookup_artist, lookup_handle
def on_pick(self, event):
#print event.artist
handle = event.artist
for lookup_artist in self.lookup_artists:
if handle in lookup_artist:
artist = lookup_artist[handle]
artist.set_visible(not artist.get_visible())
self.update()
def on_click(self, event):
if event.button == 3:
visible = False
elif event.button == 2:
visible = True
else:
return
for lookup_artist in self.lookup_artists:
for artist in lookup_artist.values():
artist.set_visible(visible)
self.update()
def update(self):
for idx, lookup_artist in enumerate(self.lookup_artists):
for artist in lookup_artist.values():
handle = self.lookup_handles[idx][artist]
if artist.get_visible():
handle.set_visible(True)
else:
handle.set_visible(False)
self.figures[idx].canvas.draw()
def show(self):
plt.show()
按如下方式使用:
leg1 = ax1.legend(loc='upper left', bbox_to_anchor=(1.05, 1), ncol=2, borderaxespad=0)
leg2 = ax2.legend(loc='upper left', bbox_to_anchor=(1.05, 1), ncol=2, borderaxespad=0)
fig.subplots_adjust(right=0.7)
interactive_legend = InteractiveLegend()
interactive_legend.add_legends(leg1)
interactive_legend.add_legends(leg2)
interactive_legend.init_legends()
interactive_legend.show()
受@JoeKington答案的启发,这里是我使用的一个稍加修改的版本,它不需要ax,fig,但可以直接使用plt.plot。。。;此外,plt.legend不在主要对象的范围内: 准备好使用示例PLTInterActiveGend.py: 用作图书馆:
import numpy as np
import matplotlib.pyplot as plt
import pltinteractivelegend
for i in range(20):
plt.plot(np.random.randn(1000), label=i)
plt.legend()
leg = pltinteractivelegend.InteractiveLegend() # mandatory: keep the object with leg = ...; else it won't work
plt.show()
为了丰富您的问题,您可以通过点击gnuplot中的图例字幕来选择图表上显示的线条,例如,我不确定您是否愿意从pyplot更改为另一个工具gnuplot,但是如果你想跟上python并使用gnuplot,有一个“gnuplot.py”接口,这正是我想要的功能。我将深入研究它,看看它与我的程序配合得如何。更新:我将放弃gnuplot。这对我来说不是很好。这正是我想要的功能!我试图找到一些奇怪的解决方法,比如使用带有复选框的Tkinter GUI,每次更改选择时都会重新绘制图形。这是更容易,但它仍然显示隐藏的阴谋传说!虽然这是一个非常有用的答案,但我不得不求助于经过一些修改的原始链接代码,因为除了这里指定的代码外,我尝试的几乎所有标签文本都出现了上面的代码错误。@jhin我更新了本例中的代码;它现在还可以与其他标签一起使用。你能验证吗?@Basj I工作,你只需再次点击pan的工具按钮,取消选择放大镜工具。
import numpy as np
import matplotlib.pyplot as plt
class InteractiveLegend(object):
def __init__(self, legend=None):
if legend == None:
legend = plt.gca().get_legend()
self.legend = legend
self.fig = legend.axes.figure
self.lookup_artist, self.lookup_handle = self._build_lookups(legend)
self._setup_connections()
self.update()
def _setup_connections(self):
for artist in self.legend.texts + self.legend.legendHandles:
artist.set_picker(10) # 10 points tolerance
self.fig.canvas.mpl_connect('pick_event', self.on_pick)
self.fig.canvas.mpl_connect('button_press_event', self.on_click)
def _build_lookups(self, legend):
labels = [t.get_text() for t in legend.texts]
handles = legend.legendHandles
label2handle = dict(zip(labels, handles))
handle2text = dict(zip(handles, legend.texts))
lookup_artist = {}
lookup_handle = {}
for artist in legend.axes.get_children():
if artist.get_label() in labels:
handle = label2handle[artist.get_label()]
lookup_handle[artist] = handle
lookup_artist[handle] = artist
lookup_artist[handle2text[handle]] = artist
lookup_handle.update(zip(handles, handles))
lookup_handle.update(zip(legend.texts, handles))
return lookup_artist, lookup_handle
def on_pick(self, event):
handle = event.artist
if handle in self.lookup_artist:
artist = self.lookup_artist[handle]
artist.set_visible(not artist.get_visible())
self.update()
def on_click(self, event):
if event.button == 3:
visible = False
elif event.button == 2:
visible = True
else:
return
for artist in self.lookup_artist.values():
artist.set_visible(visible)
self.update()
def update(self):
for artist in self.lookup_artist.values():
handle = self.lookup_handle[artist]
if artist.get_visible():
handle.set_visible(True)
else:
handle.set_visible(False)
self.fig.canvas.draw()
if __name__ == '__main__':
for i in range(20):
plt.plot(np.random.randn(1000), label=i)
plt.legend()
leg = InteractiveLegend()
plt.show()
import numpy as np
import matplotlib.pyplot as plt
import pltinteractivelegend
for i in range(20):
plt.plot(np.random.randn(1000), label=i)
plt.legend()
leg = pltinteractivelegend.InteractiveLegend() # mandatory: keep the object with leg = ...; else it won't work
plt.show()