Matplotlib savefig循环在图形中添加了先前的图形

Matplotlib savefig循环在图形中添加了先前的图形

阅读更多:Matplotlib 教程

背景

在进行数据可视化时,Matplotlib是非常常见的一个Python库。其中,savefig函数可以将当前图形保存到指定路径的文件中。但是可以发现当多次调用savefig函数时,会将前面所画的图形也一并添加在当前保存的图形中。这样会导致图形的混乱,使得我们无法获取正确的图形结果。本文将提供解决这一问题的方法。

情况介绍

以下是一个简单例子,显示在使用Matplotlib的savefig时所遇到的情况:

import matplotlib.pyplot as plt

fig = plt.figure()

for i in range(3):
    plt.plot([1, 2, 3], [i, i+1, i+2])
    plt.savefig(f"plot_{i}.png")

plt.show()

现在我们看一下生成的png文件。

from PIL import Image

img0 = Image.open("plot_0.png")
img1 = Image.open("plot_1.png")
img2 = Image.open("plot_2.png")

figure = plt.figure()
figure.set_size_inches(img0.size[0]/72.0, img0.size[1]/72.0)

plt.imshow(img0)
plt.show()

figure = plt.figure()
figure.set_size_inches(img1.size[0]/72.0, img1.size[1]/72.0)

plt.imshow(img1)
plt.show()

figure = plt.figure()
figure.set_size_inches(img2.size[0]/72.0, img2.size[1]/72.0)

plt.imshow(img2)
plt.show()

可见,虽然我们使用了三次savefig函数,保存了不同的图形,但所生成的png文件却是如下的效果:

也就是说,后两张图形追加了前面绘图的内容。这样就不能正确地进行数据可视化。如何解决这个问题呢?

问题分析

首先我们需要了解,Matplotlib图形的绘制过程分为两个阶段:第一阶段是图形的构建,即fig=plt.figure();第二阶段就是画图阶段,即在fig中添加各种元素如ax, line等,并调用plt.show()函数。

在每次调用savefig函数时会将整个figure中的所有元素都输出到文件,因此前面已经绘制的图形也会被保存在文件中。那么如何防止这一情况的发生呢?

解决方案

我们需要清理掉figure中上一次绘制的内容。为了实现这个功能,Matplotlib中提供了clf函数(clear Figure)可以用来清空figure。同时,因为在每次开始新的绘制任务之前都需要清空figure中内容,因此可以通过设置为常量的 figsize 来调用 plt.figure() 来保证生成的图形大小是相同的。那么,如何修改代码呢?

import matplotlib.pyplot as plt

for i in range(3):
    fig = plt.figure(figsize=(6, 4))
    plt.plot([1, 2, 3], [i, i+1, i+2])
    plt.savefig(f"plot_{i}.png")
    plt.clf()

plt.show()

我们将原来的代码做些改动,将figure构建的语句放入循环体内,并针对每个循环体内都调用clf函数清空figure中内容。由于设置的figsize大小被固定了,即使清空了figure,生成的图形也会有相同的大小。

我们再对保存的png文件进行读取。代码如下:

img0 = Image.open("plot_0.png")
img1 = Image.open("plot_1.png")
img2 = Image.open("plot_2.png")

figure = plt.figure()
figure.set_size_inches(img0.size[0]/72.0, img0.size[1]/72.0)

plt.imshow(img0)
plt.show()

figure = plt.figure()
figure.set_size_inches(img1.size[0]/72.0, img1.size[1]/72.0)

plt.imshow(img1)
plt.show()

figure = plt.figure()
figure.set_size_inches(img2.size[0]/72.0, img2.size[1]/72.0)

plt.imshow(img2)
plt.show()

可见不同文件之间已经达到了预期的效果,可以正确地进行数据可视化。

总结

本文介绍了Matplotlib的savefig函数在多次循环调用时会将前面的图形追加到当前图形中的情况,以及如何通过清空figure中的内容来避免这一情况的发生。即在每次循环开始前,都需要清理掉figure中上一次绘制的内容,并通过设置为常量的 figsize 来调用 plt.figure() 来保证生成的图形大小是相同的。这样才能正确地进行数据可视化,得到预期的结果。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程