首页 文章

Matplotlib:将网格线保留在图形后面,但y轴和x轴保持在上方

提问于
浏览
10

我很难在我的图形下绘制网格线而不会弄乱主x轴和y轴zorder:

import matplotlib.pyplot as plt
import numpy as np


N = 5
menMeans = (20, 35, 30, 35, 27)
menStd =   (2, 3, 4, 1, 2)

ind = np.arange(N)  # the x locations for the groups
width = 0.35       # the width of the bars

fig, ax = plt.subplots()
rects1 = ax.bar(ind, menMeans, width, color='r', yerr=menStd, alpha=0.9, linewidth = 0,zorder=3)

womenMeans = (25, 32, 34, 20, 25)
womenStd =   (3, 5, 2, 3, 3)
rects2 = ax.bar(ind+width, womenMeans, width, color='y', yerr=womenStd, alpha=0.9, linewidth = 0,zorder=3)

# add some
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind+width)
ax.set_xticklabels( ('G1', 'G2', 'G3', 'G4', 'G5') )

ax.legend( (rects1[0], rects2[0]), ('Men', 'Women') )

fig.gca().yaxis.grid(True, which='major', linestyle='-', color='#D9D9D9',zorder=2, alpha = .9)
[line.set_zorder(4) for line in ax.lines]

def autolabel(rects):
    # attach some text labels
    for rect in rects:
        height = rect.get_height()
        ax.text(rect.get_x()+rect.get_width()/2., 1.05*height, '%d'%int(height),
                ha='center', va='bottom')

autolabel(rects1)
autolabel(rects2)

plt.show()

这个例子来自matplotlib自己的,我稍微调整了一下,以展示如何使问题出现 . 我无法发布图像,但如果运行代码,您会看到条形图绘制在水平网格线上方以及x和y轴上方 . 我不希望图形隐藏x和y轴,特别是当刻度线也被阻挡时 .

4 回答

  • 2

    我有同样的问题,在轴上方绘图为@ luke_16 . 就我而言,当使用选项 ax.set_axisbelow(True) 来设置图表后面的研磨时,就会出现这种情况 .

    我对这个bug的解决方法是,不是使用板载网格,而是模拟它:

    def grid_selfmade(ax,minor=False):
        y_axis=ax.yaxis.get_view_interval()
        for xx in ax.xaxis.get_ticklocs():
            ax.plot([xx,xx],y_axis,linestyle=':',linewidth=0.5,zorder=0)
        if minor==True:
            for xx in ax.xaxis.get_ticklocs(minor=True):
                ax.plot([xx,xx],y_axis,linestyle=':',linewidth=0.5,zorder=0)
        x_axis=ax.xaxis.get_view_interval()
        for yy in ax.yaxis.get_ticklocs():
            ax.plot(x_axis,[yy,yy],linestyle=':',linewidth=0.5,zorder=0,)
        if minor==True:
            for yy in ax.yaxis.get_ticklocs(minor=True):
                ax.plot(x_axis,[yy,yy],linestyle=':',linewidth=0.5,zorder=0)
    

    此函数只需要当前的轴实例,然后在主要刻度处的所有其他位置后面绘制类似板载的网格(对于次要刻度也可选) .

    为了使轴和轴在图表顶部打勾,有必要将 ax.set_axisbelow(False) 留给 False 而不要在图中使用 zorder > 2 . 我通过改变代码中plot-commands的顺序来管理没有任何 zorder -option的图的zorder .

  • 5

    一个更简单和更好的解决方案是从网格命令复制线并禁用网格,然后再次添加行,但具有正确的zorder:

    ax.grid(True)
    lines = ax1.xaxis.get_gridlines().copy() + ax1.yaxis.get_gridlines().copy()
    ax.grid(False)
    for l in lines:
        ax1.add_line(l)
        l.set_zorder(0)
    
  • 0

    我试过matplotlib 1.2.1,1.3.1rc2和master(commit 06d014469fc5c79504a1b40e7d45bc33acc00773)

    要使轴刺在杆上,您可以执行以下操作:

    for k, spine in ax.spines.items():  #ax.spines is a dictionary
        spine.set_zorder(10)
    

    EDIT

    似乎我无法让刻度线位于条形图的顶部 . 我试过了

    1. ax.tick_params(direction='in', length=10, color='k', zorder=10)
       #This increases the size of the lines to 10 points, 
       #but the lines stays hidden behind  the bars
    2. for l in ax.yaxis.get_ticklines():
           l.set_zorder(10)
    

    和其他一些没有结果的方式 . 似乎在绘制条形时它们被放在顶部并且zorder被忽略

    解决方法可能是向外绘制刻度线

    ax.tick_params(direction='out', length=4, color='k', zorder=10)
    

    或者向内和向外,使用 direction='inout'

    EDIT2

    在@tcaswell评论之后我做了一些测试 .

    如果 ax.bar 函数中的 zorder 设置为<= 2,则在条形图上方绘制轴,刻度线和网格线 . 如果valus> 2.01(轴的默认值),则在轴,刻度线和网格的顶部绘制条形图 . 然后可以为棘刺设置更大的值(如上所述),但是任何改变滴答线的 zorder 的尝试都会被忽略(尽管值会在相应的艺术家上更新) .

    我已经尝试将 zorder=1 用于 barzorder=0 作为网格,并且网格被绘制为 on top 的条形图 . 所以zorder被忽略了 .

    recap

    在我看来,滴答线和网格 zorder 只是被忽略并保持默认值 . 对我来说,这是一个与 bar 或某些 patches 有关的错误 .

    顺便说一句,我记得在使用 imshow 时成功更改了刻度线中的zorder

  • 1

    当我在后台有网格线时,我遇到了在绘图线下方绘制轴的问题:

    ax.yaxis.grid()  # grid lines
    ax.set_axisbelow(True)  # grid lines are behind the rest
    

    对我有用的解决方案是将 plot() 函数的 zorder 参数设置为1到2之间的值 . 它不是立即清楚,但是zorder值可以是任何数字 . 从matplotlib.artist.Artist类的文档:

    set_zorder(level)设置艺术家的zorder . 首先绘制具有较低zorder值的艺术家 . ACCEPTS:任何数字

    因此:

    for i in range(5):
        ax.plot(range(10), np.random.randint(10, size=10), zorder=i / 100.0 + 1)
    

    我没有检查过这个范围之外的值,也许它们也可以工作 .

相关问题