如何将pyplot函数附加到图形实例?

12

之前我在使用Matplotlib时遇到了多个图像之间的干扰问题。最终我发现这是由于某些pyplot函数没有与它们所属的图像实例关联而导致的,在并行创建的其他图像实例中却能够呈现出来。

以下是一些示例代码:

from django.http import HttpResponse
from numpy import arange, meshgrid
from matplotlib.mlab import bivariate_normal

def show_chart(request):
    delta = 0.025
    x = arange(-3.0, 3.0, delta)
    y = arange(-2.0, 2.0, delta)
    X, Y = meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)

    from matplotlib.pyplot import figure, contour
    fig1 = figure(figsize=(4, 4), facecolor='white')
    contour(X, Y, Z)

    response = HttpResponse(content_type='image/png')
    fig1.savefig(response, format='png')
    fig1.clear()
    return response

上面的示例中,轮廓图pyplot函数可以在fig1中呈现,但有时也会在并行生成的其他一些图中出现。 非常令人讨厌。 有没有办法将轮廓pyplot函数附加到fig1?

2个回答

21

作为对这里正在发生的事情的一点解释,matplotlib 有两个半独立的接口;状态机和OO接口。

状态机代码旨在在交互式shell中工作(并模仿matlab的界面)。它通过用一组命令包装OO接口来跟踪当前的 figureaxes是什么。当您使用来自matplotlib.pyplot的命令时(我猜您的代码中有一个from matploblib.pyplot import *),它更或多或少相当于执行 gcf().gca().contour(...)。创建新图时,它会自动变为当前图(如果您在使用交互式shell,则希望出现这种行为),因此您看到的行为是“正确”的行为。状态机接口还具有使图形在需要时重新绘制、管理GUI事件循环等内容的代码(您需要执行的所有内容以使交互式接口平稳运行)。正如Hayden在评论中提到的那样,运行ipython --pylab将自动运行from matplotlib.pyplot import *,这将为您提供非常好的交互式shell。

OO接口旨在以编程方式处理matplotlib。虽然它增加了冗长性(您现在必须做大部分状态机的工作),但它在清晰度上弥补了这一点。在OO模型中,大多数(也许全部)绘图功能都与Axes对象相关联(文档)(因为可以有多个轴与一个图形相关联(例如使用gridspec的子图)。

解决您的问题的另一种方法是

ax = fig1.gca()

这将从fig1中获取当前的坐标轴,如果需要会自动创建一个。如果您记住了您的图形对象,而没有记住您的坐标轴对象,并且希望向图形中添加另一个图表,则此方法可能很有用。


谢谢,这帮助我更好地理解了问题! - Meilo
值得注意的是,运行 ipython --pylab 命令会自动导入 from matploblib.pyplot import * - Andy Hayden

12

您可以创建一个子图,然后调用该子图的contour方法:

fig1 = figure(figsize=(4, 4), facecolor='white')
ax = fig1.add_subplot(111)
ax.contour(X, Y, Z)

plt.subplots函数可以一次性方便地创建一个图和多个子图:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

这是一个完美的答案:运行得很好,只需要我在我的代码库中添加三个符号“ax.”。非常感谢! - Meilo
感谢您。 - bmu
谢谢你的回答,非常有用。 - Luke Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接