【问题标题】:Strange matplotlib zorder behavior with legend and errorbar带有图例和错误栏的奇怪 matplotlib zorder 行为
【发布时间】:2013-05-27 09:22:33
【问题描述】:

我遇到了图例和错误栏绘图命令的一个相当奇怪的行为。我正在使用带有matplotlib 1.1.1的Python xy 2.7.3.1 下面的代码举例说明了观察到的行为:

import pylab as P
import numpy as N

x1=N.linspace(0,6,10)
y1=N.sin(x1)
x2=N.linspace(0,6,5000)
y2=N.sin(x2)
xerr = N.repeat(0.01,10)
yerr = N.repeat(0.01,10)

#error bar caps visible in scatter dots
P.figure()
P.subplot(121)
P.title("strange error bar caps")
P.scatter(x1,y1,s=100,c="k",zorder=1)
P.errorbar(x1,y1,yerr=yerr,xerr=xerr,color="0.7", 
    ecolor="0.7",fmt=None, zorder=0)
P.plot(x2,y2,label="a label")
P.legend(loc="center")

P.subplot(122)
P.title("strange legend behaviour")
P.scatter(x1,y1,s=100,c="k",zorder=100)
P.errorbar(x1,y1,yerr=yerr,xerr=xerr,color="0.7", 
    ecolor="0.7",fmt=None, zorder=99)
P.plot(x2,y2,label="a label", zorder=101)
P.legend(loc="center")
P.show()

产生这个情节:

如您所见,误差条上限正在覆盖散点图。如果我将 zorder 增加得足够多,则不会再发生这种情况,但是情节线会覆盖图例。我怀疑这个问题与 this zorder problem 和 matplotlib 有关。

快速、肮脏、老套的解决方案也值得赞赏。

编辑(感谢@nordev):期望的结果如下:

  • 误差线以及结束大写应位于散点图点下方。
  • 线图应位于散点和误差线上方
  • 传奇高于一切

根据您的回答调整 zorder:

  • P.legend(zorder=100) --> self.legend_ = mlegend.Legend(self, handles, labels, **kwargs) TypeError: __init__() got an unexpected keyword argument 'zorder'
  • P.errorbar(zorder=0), P.scatter(zorder=1), ... 正如您正确建议的那样,仍然产生相同的图,误差条上限仍在散点上方。我相应地更正了上面的示例。

【问题讨论】:

  • 对我来说这似乎是正确的。具有最高zorder 的对象位于顶部,因此根据代码,上面的图似乎是正确的。如果您想要顶部的图例,只需为此指定 zorder 参数。此外,您无需指定希望输出的外观,因此提供解决方案并非易事。
  • legend 没有 z 顺序,因此我不能给它这个论点。我将在问题中重新表述想要的结果,感谢您指出这一点。在左图中,误差线在散点图下方,但误差线上限在上方,这是错误的。在正确工作的正确图片上,但线在图例上方,这是无意的。
  • 您可以使用P.legend(loc="center").set_zorder(102) 更改legend 的zorder,使其在第二个子图中位于顶部。此外,在您上面的评论中,您说误差线位于散点图下方,这对我来说似乎不是这样,我怀疑它也不适合你。 t 是否使用大于 0.01 的yerrxerr 更容易查看。
  • 另外,请参阅下面的答案,因为我解释了为什么你会得到你得到的输出。我正在使用 Python 2.7.5。和 matplotlib 1.2.1。
  • 您上面链接的 zorder 问题在 matplotlib 1.2.1 中已修复,因此如果可能,您应该更新您的 matplotlib 以解决这些问题。

标签: python matplotlib


【解决方案1】:

根据您发布的代码,创建的图是正确的。 最低 zorder 的对象放在底部,而最高 zorder 的对象放在顶部。您链接到的 zorder 问题已在 matplotlib 版本 1.2.1 中修复,因此您应该尽可能更新安装。

在您的第一个子图中,误差条绘制在散点上方,因为 errorbar 是用 zorder=2 调用的,而 scatter 是用 zorder=1 调用的——这意味着误差条将覆盖散点。

在您的第二个子图中,您使用zorder=99 调用了errorbar,使用zorder=100 调用了scatter,使用zorder=101 调用了plot - 这意味着误差条将放置在散点和线的下方.

legend 显示在第一个子图中的行顶部,而它在第二个子图中位于同一行的顶部,是因为您没有明确设置图例对象a zorder 值,这意味着它将使用其默认值(我相信是 5)。要更改图例 zorder,只需使用 P.legend(loc="center").set_zorder(102),其中 102 是所需的 zorder 值。

因此,为了产生您想要的输出,您必须相应地设置 zorder 参数。由于您没有在问题中描述您的 desired 输出,因此我很难“纠正”您的代码,因为我不知道您希望按什么顺序绘制对象。

【讨论】:

  • 非常感谢您的努力。我将尽快获得 1.2.1 版本 - 讨厌使用已弃用的版本浪费我的时间 b/c -.-
  • 我相信在 matplotlib 1.1.1 中也有解决此问题的方法,但这远不如 1.2.1 中的优雅和直观。避免问题的最简单(也是最预防性)的方法是让你的 matplotlib 保持最新。
  • @Faultier 有点相反,使用旧软件的好处是大多数错误都有已知的解决方法,而新软件您甚至不知道错误是什么;)
  • @tcaswell 好点!在我看来,新旧软件的使用“总是”有利有弊,所以最后我想这取决于用户什么更重要(例如,新功能与已知的错误解决方法等.)。我在之前的评论中应该更清楚;避免已知问题(至少在某种程度上)的最简单方法是使软件保持最新状态。
猜你喜欢
  • 2014-10-06
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
相关资源
最近更新 更多