plt.pause导致子图放置不正确

时间:2019-04-25 20:26:29

标签: python matplotlib jupyter-notebook

我正在学习this教程,但偶然发现了我不了解的内容。

想法是要有一个绘制图像的函数。然后在定义子图的循环中调用此函数:

最小示例

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np    

def show_image(image):
    """Show image"""
    plt.imshow(image)

def show_image_wait(image):
    """show image, and wait a little bit. similar implementation than in the tutorial"""
    plt.imshow(image)
    plt.pause(0.001)

现在,在循环中调用两个函数:
不用等待:

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image(image)

# expected output: 1 row, with 4 images side by side
# actual output: 1 row, with 4 images, side by side

等待中,但是:

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image_wait(image)

# expected output: 1 row, with 4 images side by side
# actual output: 4 rows, with 1 images each

上面链接的教程中使用了类似于show_image_wait的功能,其中所有图像看起来都正确定位。
我不明白为什么在我的情况下而不是在链接的示例中,稍等一下会覆盖子图的位置。

所有这些都发生在Jupyter笔记本电脑中

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我认为如果在for循环后使用plt.show()会起作用,但是在JuPyTer笔记本中,绘图是inline。解决方法可能是使用time.sleep(0.001)。您可以尝试看看它是否符合您的目的。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np    
import time

def show_image_wait(image):
    """show image, and wait a little bit. similar implementation than in the tutorial"""
    plt.imshow(image)
    time.sleep(0.001)

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image_wait(image)    

答案 1 :(得分:1)

看到几行的原因是,每次循环运行都会产生一个新图形。独立图形在jupyter输出单元格中彼此下方放置。
这又是由于屏幕上绘制了最后一次循环迭代中的一个而导致的,因此,当另一次调用plt.subplot时,则不存在活动图形-因此将创建一个新图形。

所有这些的根本原因是plt.pause(..)所做的不仅仅是暂停。相反,它处理图形上可能发生的事件,并最终以交互模式绘制显示图形。

source of plt.pause

manager = _pylab_helpers.Gcf.get_active()
if manager is not None:
    canvas = manager.canvas
    if canvas.figure.stale:
        canvas.draw_idle()
    show(block=False)                 #  <----  here the figure is shown.
    canvas.start_event_loop(interval)
else:
    time.sleep(interval)

我在注释中标记了关键行。

因此,总的来说,如果您想要真正的暂停,如“在x秒内不做任何事情”,plt.pause不太适合。总的来说,在带有inline后端的jupyter笔记本中它的实用性还有些疑问,因为该后端不提供任何交互性。