如何单独显示图形?
假设我在matplotlib中有两个图形,每个图形里有一个绘图:
import matplotlib.pyplot as plt
f1 = plt.figure()
plt.plot(range(0,10))
f2 = plt.figure()
plt.plot(range(10,20))
然后我一次性显示这两个图形
plt.show()
有没有办法单独显示它们,也就是说,只显示 f1
呢?
或者更好的是:我该如何像下面这个“理想”的代码那样单独管理这些图形(这个代码是不能用的):
f1 = plt.figure()
f1.plot(range(0,10))
f1.show()
7 个回答
我觉得我来得有点晚,不过……
在我看来,你需要的是matplotlib的面向对象的API。在matplotlib 1.4.2版本中,使用IPython 2.4.1和Qt4Agg后端,我可以这样做:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1) # Creates figure fig and add an axes, ax.
fig2, ax2 = plt.subplots(1) # Another figure
ax.plot(range(20)) #Add a straight line to the axes of the first figure.
ax2.plot(range(100)) #Add a straight line to the axes of the first figure.
fig.show() #Only shows figure 1 and removes it from the "current" stack.
fig2.show() #Only shows figure 2 and removes it from the "current" stack.
plt.show() #Does not show anything, because there is nothing in the "current" stack.
fig.show() # Shows figure 1 again. You can show it as many times as you want.
在这种情况下,plt.show()会显示“当前”堆栈中的内容。你可以指定figure.show(),但前提是你使用的是图形用户界面(GUI)后端(比如Qt4Agg)。否则,我觉得你可能需要深入研究matplotlib的内部,才能找到解决办法。
记住,大多数(可能所有?)的plt.*函数其实只是figure和axes方法的快捷方式和别名。它们在顺序编程中非常有用,但如果你打算以更复杂的方式使用它们,很快就会遇到阻碍。
在Matplotlib 1.0.1版本之前,show()
每个程序只能调用一次,即使在某些环境下(比如某些后端或平台)看起来可以多次调用。
其实,真正负责绘图的函数是draw()
:
import matplotlib.pyplot as plt
plt.plot(range(10)) # Creates the plot. No need to save the current figure.
plt.draw() # Draws, but does not block
raw_input() # This shows the first figure "separately" (by waiting for "enter").
plt.figure() # New window, if needed. No need to save it, as pyplot uses the concept of current figure
plt.plot(range(10, 20))
plt.draw()
# raw_input() # If you need to wait here too...
# (...)
# Only at the end of your program:
plt.show() # blocks
需要注意的是,show()
是一个无限循环,它的设计是为了处理各种图形中的事件(比如调整大小等)。如果在脚本开始时调用matplotlib.ion()
,原则上可以不调用draw()
,不过我在某些平台和后端上见过这个不太好使。
我觉得Matplotlib并没有提供一个可以选择性显示图形的机制;这意味着用figure()
创建的所有图形都会被显示。如果你只需要依次显示不同的图形(无论是在同一个窗口还是不同窗口),可以像上面的代码那样做。
现在,上面的解决方案在简单的情况下和某些Matplotlib后端中可能足够用了。有些后端很友好,即使你没有调用show()
,也能让你与第一个图形进行交互。但据我了解,它们并不一定要这么友好。最稳妥的方法是让每个图形的绘制在一个单独的线程中进行,并在每个线程中最后调用show()
。我相信这基本上就是IPython所做的。
上面的代码在大多数情况下应该是足够的。
PS:现在,在Matplotlib 1.0.1及以上版本中,show()
可以多次调用(在大多数后端中)。
当然可以。你可以用 add_subplot
来添加一个 Axes
(坐标轴)。(这里修改了 import
的部分。)(这里修改了 show
的部分。)
import matplotlib.pyplot as plt
f1 = plt.figure()
f2 = plt.figure()
ax1 = f1.add_subplot(111)
ax1.plot(range(0,10))
ax2 = f2.add_subplot(111)
ax2.plot(range(10,20))
plt.show()
另外,你也可以使用 add_axes
。
ax1 = f1.add_axes([0.1,0.1,0.8,0.8])
ax1.plot(range(0,10))
ax2 = f2.add_axes([0.1,0.1,0.8,0.8])
ax2.plot(range(10,20))