Когда использовать cla(), clf() или close() для очистки графика
Matplotlib предлагает эти функции:
cla() # Clear axis
clf() # Clear figure
close() # Close a figure window
Когда я должен использовать каждую функцию и что именно она делает?
Переведено автоматически
Ответ 1
Все они выполняют разные функции, поскольку matplotlib использует иерархический порядок, в котором окно рисунка содержит рисунок, который может состоять из множества осей. Кроме того, существуют функции из интерфейса pyplot и методы в Figure
классе. Ниже я рассмотрю оба случая.
интерфейс pyplot
pyplot
это модуль, который собирает пару функций, позволяющих функционально использовать matplotlib. Я здесь предполагаю, что pyplot
был импортирован как import matplotlib.pyplot as plt
. В этом случае есть три разные команды, которые удаляют содержимое:
Смотрите matplotlib.pyplot
Функции:
plt.cla()
очищает ось, то есть текущую активную ось на текущем рисунке. Остальные оси остаются нетронутыми.plt.clf()
очищает весь текущий рисунок со всеми его осями, но оставляет окно открытым, так что его можно повторно использовать для других графиков.plt.close()
закрывает окно, которое будет текущим окном, если не указано иное.
Таким образом, какие функции подходят вам лучше всего, зависит от вашего варианта использования.
Кроме того, функция close()
позволяет указать, какое окно следует закрыть. Аргументом может быть либо число, либо имя, присвоенное окну при его создании с помощью figure(number_or_name)
, либо это может быть экземпляр рисунка, fig
полученный, т. е. с помощьюfig = figure()
. Если не указан аргумент для close()
, текущее активное окно будет закрыто. Кроме того, существует синтаксис close('all')
, который закрывает все рисунки.
методы класса Figure
Кроме того, Figure
класс предоставляет методы для очистки фигур. Далее я предположу, что fig
является экземпляром Figure
:
fig.clf()
очищает всю фигуру. Этот вызов эквивалентен plt.clf()
только если fig
это текущая фигура.
fig.clear()
является синонимом fig.clf()
Обратите внимание, что even del fig
не закроет связанное окно рисунка. Насколько я знаю, единственный способ закрыть окно рисунка - использовать plt.close(fig)
, как описано выше.
Ответ 2
Есть только одно предостережение, которое я обнаружил сегодня. Если у вас есть функция, которая вызывает график много раз, вам лучше использовать plt.close(fig)
вместо fig.clf()
почему-то первое не накапливается в памяти. Короче говоря, если вас беспокоит память, используйте plt.close (рис.) (Хотя кажется, что есть способы получше, перейдите к концу этого комментария, чтобы найти соответствующие ссылки).
Таким образом, следующий скрипт выдаст пустой список:
for i in range(5):
fig = plot_figure()
plt.close(fig)
# This returns a list with all figure numbers available
print(plt.get_fignums())
В то время как этот будет выдавать список с пятью цифрами в нем.
for i in range(5):
fig = plot_figure()
fig.clf()
# This returns a list with all figure numbers available
print(plt.get_fignums())
Из приведенной выше документации мне непонятно, в чем разница между закрытием рисунка и закрытием окна. Возможно, это прояснит ситуацию.
Если вы хотите попробовать полный скрипт, у вас есть:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(1000)
y = np.sin(x)
for i in range(5):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y)
plt.close(fig)
print(plt.get_fignums())
for i in range(5):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y)
fig.clf()
print(plt.get_fignums())
Если проблема с памятью, кто-то уже опубликовал обходной путь в SO, смотрите:
Создайте фигуру с подсчетом ссылок
Ответ 3
plt.cla() означает очистить текущую ось
plt.clf() означает очистить текущий рисунок
также есть plt.gca() (получение текущей оси) и plt.gcf() (получение текущего рисунка)
Подробнее читайте здесь: Matplotlib, Pyplot, Pylab и т.д.: в чем разница между ними и когда использовать каждый из них?
Ответ 4
Когда использовать cla(), clf() или close()
Как объяснил Дэвид Цвикер, все эти методы очищают разные вещи. В этом посте добавлено несколько примеров, которые помогут прояснить, когда их использовать.
Если вы хотите повторно использовать определенные конфигурации фигуры (facecolor, dpi, layout и т.д.) Для другой фигуры, используйте
fig.clf()
, чтобы очистить текущие объекты (включая оси) на фигуре. Обратите внимание, что при этом не удаляется ранее созданный экземпляр Figure, а только очищаются объекты на нем. Итак, в следующем коде один экземпляр Figure повторно используется для создания двух файлов изображений.fig, ax = plt.subplots() # instantiate a Figure and an Axes
ax.plot([0,1,2]) # draw a line plot
fig.savefig('images/img1.png')
fig.clf() # clear Figure (removes Axes)
ax = fig.add_subplot() # add new Axes to previously instantiated `fig`
ax.plot([1,2,0,0,2,1], 'o') # draw a scatter plot
fig.savefig('images/img2.png')Поскольку
fig.clf()
оси удаляются, важно добавить к ним новую, чтобы что-то построить.Если вы хотите повторно использовать фигуру, но изменить оси на ней, используйте
ax.cla()
для очистки текущих объектов (например, тиков, заголовков, графиков и т.д.) На осях. В частности, положение осей на фигуре является важным атрибутом, который можно использовать повторно (например, фигура с маленькими осями может быть наложена на оси большего размера).Если хотите закрыть окно рисунка, используйте
plt.close()
. Это особенно полезно, если вы используете IDE с интерактивным режимом, таким как Jupyter или Spyder, и вы не хотите видеть рисунки, создаваемые вашим скриптом. Если вы используете оболочку Python, такую как IDLE (которая поставляется с установкой Python), то она буквально закрывает окно, в котором показан рисунок. Даже если окно закрывается, экземпляр Figure все еще находится в памяти вместе с любыми объектами, определенными в нем. Например, в следующем коде, даже еслиfig
закрыт, с ним все еще можно работать. Однако, поскольку фигура / оси не были очищены, все, что было вfig
, сохраняется.fig, ax = plt.subplots() # instantiate a Figure and an Axes
ax.plot([0,1,2]) # draw a line plot
fig.savefig('images/img1.png') # save the line plot
plt.close(fig) # close `fig`
ax.plot([1,2,0,0,2,1], 'o') # draw a scatter plot on top of the previously plotted lineplot
fig.savefig('images/img2.png') # save scatter + line plot
Использование памяти
Хеберто Майоркин указывает, что это plt.close()
экономит память. Однако, как показывают следующие схемы распределения памяти, если в цикле необходимо создать много похожих изображений, очистка с помощью clf()
или cla()
на самом деле более экономит память, чем закрытие окна и создание нового экземпляра рисунка с помощью plt.close()
.
Однако есть оговорка, что, поскольку cla()
/clf()
предназначены для повторного использования ранее определенных осей / фигур, важно определить объект Figure, который будет повторно использоваться вне цикла (который создает файлы изображений). Я также включил "неправильные" способы использования cla()
и clf()
в тесте (где новый экземпляр фигуры создается каждый раз, когда рисуется новая фигура), которые действительно дороже, чем создание новой фигуры и замыкание ее в цикле.
close:
current memory usage is 12,456 KB; peak was 13,402 KB.
======================================================
cla:
current memory usage is 899 KB; peak was 1,451 KB.
======================================================
clf:
current memory usage is 3,806 KB; peak was 8,061 KB.
======================================================
clf_wrong:
current memory usage is 7,392 KB; peak was 10,494 KB.
======================================================
cla_wrong:
current memory usage is 29,174 KB; peak was 29,650 KB.
======================================================
Код, используемый для получения вышеуказанного результата:
import os
import tracemalloc
import matplotlib.pyplot as plt
def close(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
plt.close(fig)
def cla(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
for i in range(n):
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
ax.cla()
def clf(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
for i in range(n):
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
fig.clf()
def cla_wrong(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
ax.cla()
def clf_wrong(n):
for i in range(n):
fig = plt.figure(facecolor='white', figsize=(6,3), dpi=36)
ax = fig.add_subplot()
ax.plot([100, 0, i])
fig.savefig(f'{i}.png')
fig.clf()
if __name__ == '__main__':
for func in (close, cla, clf, clf_wrong, cla_wrong):
tracemalloc.start()
func(100)
size, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
# delete the saved image files
for f in os.listdir():
if f.endswith('.png'):
os.remove(f)
print(f"{func.__name__}:\ncurrent memory usage is {size/1024:,.0f} KB; \
peak was {peak/1024:,.0f} KB.")
print("======================================================")