Matplotlib意外地隐藏了多边形

时间:2015-10-26 10:50:16

标签: python debugging matplotlib plot

我正在使用matplotlib 1.4.3 python 3.3。我想用多个子图绘制多个数字。我正面临某种让我感到无聊的错误:

  

当我在图中使用fill()boxplot()方法时,如果图形不是第一个创建的,则隐藏这些函数的结果。

这个错误似乎与多边形显示和matplotlib环境状态有关。

当解析只有一个数字时,一切正常。当我解析多个数字时,第一个是好的。但是,在其他所有后续数据中,除了隐藏的 wiskerbox 多边形外,一切都是正确的。

每个绘图代码都包含在一个函数中,该函数接受位置参数*args**kwargs。让我们说签名是:

def myplot(t, x, *args, *kwargs):
    # [...]
    hFig = plt.figure()
    # [...]
    return hFig

据我了解python机制,在解析函数调用之后,除了matplotlib环境存储在其中的内容之外,必须没有任何活动(我不使用全局变量)全局命名空间变量

在每次通话中,我close()我的身材,在离开功能之前我还尝试了hFig.clf(),但它无法解决问题。

每个绘图都包含在打印机(装饰器)中以添加通用功能:

def myprint(func):
     def inner(*args, **kwargs)
          # [...]
          hFig = func(*args, **kwargs)
          # [...]
      return inner

到目前为止我尝试过:

  • wiskerbox 多边形 zscore增加,无效;
  • 在不同的线程中执行绘图生成,不起作用;
  • 在不同的进程中执行绘图生成,但我必须更改我的功能签名,因为它可以被腌制。

我不想使用dillpathos,即使我不能。

看起来它是一个matplotlib环境错误,因为当我运行不同的进程时,这个环境会从头开始重新创建,并且它的工作方式应该如此。我想知道是否有办法在matplotlib脚本中重置python环境状态。如果没有,我该怎么做才能解决这个问题。

Obs。:我正在使用GridSpecs对象和subplot()方法创建我的数据。当我自己计算盒子并使用add_axes()方法时,问题就不存在了。

更新:在这里您可以找到问题的MCVE。通过这个简单的例子,我找到了使我的bug发生的行(看起来我有旧的不良Matlab行为)。 plt.hold(False)似乎改变了多边形boxplot的显示方式。而且,正如我所指出的,它与matplotlib全局命名空间变量有关。我只是误解了这种方法的工作方式,并且在每个子流程中都重置了它。

import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gspec

def bloodyplotit(t_, x_):
    hFig = plt.figure()
    gs = gspec.GridSpec(1, 4, height_ratios=[1], width_ratios=[15, 2, 3, 1])
    gs.update(left=0.10, right=0.90, top=0.90, bottom=0.25, hspace=0.05, wspace=0.05)
    plt.hold(True)
    hAxe = plt.subplot(gs[0,0])
    hAxe.plot(t_, x_)
    #plt.hold(False)   # <------------------------ This line make the scirpt bug
    hAxe = plt.subplot(gs[0,1])
    hAxe.hist(x_, orientation='horizontal')
    hAxe = plt.subplot(gs[0,3])
    hAxe.boxplot(x_)
    plt.show()


n = 1000
t = datetime.datetime.utcnow() + np.arange(n)*datetime.timedelta(minutes=1)
x = np.random.randn(1000,1)

for i in range(10):
    bloodyplotit(t, x)

1 个答案:

答案 0 :(得分:1)

这是一个产生错误的更小的脚本:

x = np.random.randn(1000)
fig, ax = plt.subplots(1, 2)
ax[0].hold(True)
ax[0].boxplot(x);
ax[1].hold(False)
ax[1].boxplot(x);

enter image description here

据我所知,这是预期的行为。根据{{​​3}}的文档,

  

当hold为True时,后续绘图命令将添加到当前轴。当hold为False时,将在下一个绘图命令中清除当前轴和图形。

Boxplot是一个复合对象:它是通过调用多个绘图命令创建的。如果hold为False,则在每个命令之间清除轴,因此箱线图的某些部分不会显示。

就个人而言,我从来没有找到过使用matplotlib 10多年来保持状态的理由。我的经验是,这样做(特别是全球性)只会引起混淆,我建议避免它。