【问题标题】:grid zorder seems not to take effect (matplotlib)网格 zorder 似乎没有生效(matplotlib)
【发布时间】:2015-10-08 23:27:29
【问题描述】:

我正在尝试使用 python 的 matplotlib 在网格上绘制散点图(1.4.3,但在其他版本上也尝试过但没有成功)。除了网格zorder 位置外,一切正常。我将网格的zorder 设置为低于scatter,但网格仍然覆盖了散点。

下面是重现问题的简单代码:

import numpy as np
from matplotlib import pyplot as plt

# create points
pnts = np.array([[1., 1.], [1., 1.2]])

# create figure
plt.grid(True, linestyle='-', color='r', zorder=1)
plt.scatter(pnts[:,0], pnts[:,1], zorder=2)
plt.ylim([0, 2])
plt.xlim([0, 2])
plt.savefig('testfig.png', dpi=350)

我明白了:
如果放大这些点,您可以看到网格位于顶部,尽管它的 zorder 较低:

这是一个错误还是我做错了什么?

【问题讨论】:

  • 试着把你想要的改成更大的,比如zorder=10
  • 谢谢,成功了!为什么zorder=2 不够用?
  • 不知道为什么zorder=2不够用。我不得不多次这样做。
  • 来自this 等,我怀疑这是一个错误——matplotlib 使用 0 和 1 作为网格线并且不注意它们的 z-order 参数。但我还没有真正看过。

标签: python matplotlib


【解决方案1】:

如果有人在多年后仍然想知道这一点(比如我自己),这是一个长期存在的问题(2015 年 9 月):

Axes.grid() not honoring specified "zorder" kwarg

引用问题:

Axes.grid() 不支持提供的自定义 zorder。相反,网格的 zorder 似乎固定在 2.5 和 2.6 之间的某个神奇值(我在 rcParams 中找不到网格 zorder 的键)。

显然到目前为止唯一的解决方案是:

只需将 2.5 添加到所有 z 顺序即可。

这个问题Matplotlib: draw grid lines behind other graph elements也有一个旧答案,但它似乎不再起作用了。

【讨论】:

  • 您还可以为播放不佳的元素设置 z-order 的负值(即zorder=-1),以将它们强制放在后面。
  • 添加 2.5 和将一个 zorder 值设置为 -1 都不适用于我尝试过的至少一个图(matplotlib 2.2.3),我认为这不是实际的解决问题。
  • 在 2021 年初,这仍然不能很好地工作。次要网格线绘制在主要网格线之上,而不管两者的 zorder。
  • 我用 -1 zorders 放置的垂直线目前不起作用。
【解决方案2】:

几年后,Gabriel 引用的 issue 已更新为以下内容,并于 2019 年 4 月关闭。

这必须是刻度线和网格线系统大修的一部分,我怀疑这可能只是更重大重构的一个组成部分,所以我认为在可预见的未来的解决方案是文档调整在#13995

对于需要具有任意 zorder 值的网格的情况,一种解决方法是使用 plot() 模拟 grid()。我编写了函数以尽可能接近地复制标准 grid() 行为(默认使用 rcParam 值)。

import matplotlib.pyplot as plt
from matplotlib import rcParams
import numpy as np

# emulate grid using Axes.plot()
def zorder_grid(ax=None, zorder=1.5, which=None, axis=None, alpha=None,
                color=None, linestyle=None, linewidth=None, **kwargs):
    # Honor rcParams values if keywords not specified
    if ax is None:
        ax = plt.gca()
    if which is None:
        which = rcParams['axes.grid.which']
    if axis is None:
        axis = rcParams['axes.grid.axis']
    if alpha is None:
        alpha = rcParams['grid.alpha']
    if color is None:
        color = rcParams['grid.color']
    if linestyle is None:
        linestyle = rcParams['grid.linestyle']
    if linewidth is None:
        linewidth = rcParams['grid.linewidth']

    # get coordinates for grid lines
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    xticks = []
    yticks = []
    if which in ['major', 'both']:
        xticks = np.concatenate((xticks, ax.get_xticks()))
        yticks = np.concatenate((yticks, ax.get_yticks()))
    if which in ['minor', 'both']:
        xticks = np.concatenate((xticks, ax.get_xticks(minor=True)))
        yticks = np.concatenate((yticks, ax.get_yticks(minor=True)))

    # plot grid using Axes.plot()
    if axis in ['x', 'both']:
        for tick in xticks:
            ax.plot([tick, tick], ylim, linestyle=linestyle, color=color,
                    linewidth=linewidth, alpha=alpha, zorder=zorder, **kwargs)
    if axis in ['y', 'both']:
        for tick in yticks:
            ax.plot(xlim, [tick, tick], linestyle=linestyle, color=color,
                    linewidth=linewidth, alpha=alpha, zorder=zorder, **kwargs)

注意事项:

  1. 必须在调用zorder_grid() 之前手动设置x 和y 限制。如果手动指定刻度,则还需要在绘制网格线之前完成。
  2. 如果轴限制和/或刻度动态变化(例如动画),则会出现问题。可能的解决方案可能是清除帧之间的轴或返回 Line2D 列表并切换可见性。

可以如下调用该函数以在 MWE 中产生所需的输出(任何 zorder

pnts = np.array([[1., 1.], [1., 1.2]])
plt.scatter(pnts[:,0], pnts[:,1])
plt.ylim([0, 2])
plt.xlim([0, 2])
zorder_grid(zorder=0.99, linestyle='-', color='r')
plt.savefig('testfig.png', dpi=350)

以上代码生成的图。

【讨论】:

    【解决方案3】:

    以下对我有用:

    ax.set_axisbelow(True)
    

    来自docs for Axes.grid 中的“备注”部分:

    轴是作为一个单位绘制的,因此绘制网格的有效 zorder 由每个轴的 zorder 决定,而不是由构成网格的 Line2D 对象的 zorder 决定。因此,要设置网格 zorder,请使用 set_axisbelow,或者为了更好地控制,请调用每个轴的 set_zorder 方法。

    此设置的默认值为

    >>> import matplotlib as mpl
    >>> mpl.rcParams["axes.axisbelow"]
    'line'
    

    根据docs for Axes.set_axisbelow,可能的值为:

    • True (zorder = 0.5):刻度线和网格线位于所有艺术家下方。
    • 'line' (zorder = 1.5):刻度线和网格线位于补丁上方(例如矩形,默认 zorder = 1),但仍在线条和标记下方(默认 zorder = 2)。
    • False (zorder = 2.5):刻度线和网格线位于补丁和线/标记上方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      相关资源
      最近更新 更多