【问题标题】:Draw grid line on SecondaryAxis - Matplotlib在次轴上绘制网格线 - Matplotlib
【发布时间】:2020-11-11 10:40:44
【问题描述】:

问题

我正在尝试使用 SecondaryAxis 的刻度绘制网格线

ax2.grid(color=color,linestyle='--')

图中什么都没有,我相信我和Format SecondaryAxis ticklabels Matplotlib的情况一样,不是吗?

但是,有没有人在不颠倒比例的情况下解决这个问题?我的意思是颠倒比例是在主轴上有百分比比例,在次轴上有正常比例。

完整代码

import matplotlib.pyplot as plt
import numpy as np

#generate dummy load duration curve
dur=2500
load = np.random.normal(60,30,dur+1)
load[::-1].sort()

x=range(0,dur+1)

perticks = np.linspace(0,1,11)
xticks = perticks*dur

# get yticks from xticks
yticks = np.interp(xticks, range(0,dur+1), load)
print(yticks)

# create figure object with axe object
fig, ax1 = plt.subplots(figsize=(16, 8))
ax1.plot(x, load)

#create second axis
ax2 = ax1.secondary_yaxis('right')

# label and color of the secondaryaxis 
perlabels = ['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%']
color ='tab:blue'

ax2.set_yticks(yticks)
ax2.set_yticklabels(labels=perlabels)
ax2.tick_params(axis='y', color=color, labelcolor=color)

# draw grid lines on the secondaryaxis
ax2.grid(color=color,linestyle='--')

# do the same for x axis
ax3 = ax1.secondary_xaxis('top')

ax3.set_xticks(xticks)
ax3.set_xticklabels(labels=perlabels)
ax3.tick_params(axis='x', color=color, labelcolor=color)

ax3.grid(color=color,linestyle='--')

输出

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    我对这个话题做了一些挖掘,并在 GitHub 上打开了一个issue。这是我发现的:

    • SecondaryAxis 是“相当新的东西”,在 matplotlib 3.1.0 中添加。 (2019 年 5 月)。甚至v.3.3.3 docs saysecondary_xaxis() 方法也是实验性的。
    • SecondaryAxis 继承自 _AxesBase,这是一个“implementation detail”。它不应该(从 v.3.3.3 开始)作为 Axes 对象工作,并且 SecondaryAxis.grid() 不应该绘制任何东西(就像 _AxesBase.grid() 那样)。虽然,我同意存在一种无效的方法是一种误导。
    • 因此,在撰写本文时,.grid() 仅被假定为在主轴上工作。

    将蓝色轴设为主轴

    • 由于.grid() 仅适用于非辅助轴,因此您将主轴设为蓝色,并将其向上和向右移动。

    代码

    # Take the x and y-ticks for transfering them to secondary axis
    xticks_orig = ax1.get_xticks()
    yticks_orig = ax1.get_yticks()
    
    # Make the primary axis blue since we want to draw grid on it
    ax1.xaxis.tick_top()
    ax1.yaxis.tick_right()
    ax1.set_xticks(xticks)
    ax1.set_yticks(yticks)
    ax1.set_yticklabels(labels=perlabels)
    ax1.set_xticklabels(labels=perlabels)
    ax1.tick_params(axis="both", color=color, labelcolor=color)
    ax1.grid(color=color, linestyle="--")
    
    # Draw the black secondary axis
    ax2 = ax1.secondary_yaxis("left")
    ax3 = ax1.secondary_xaxis("bottom")
    ax2.set_yticks(yticks_orig)
    ax3.set_xticks(xticks_orig)
    

    手动添加网格线

    你也可以手动添加网格线,像这样

    xlim = ax1.get_xlim()
    for y in ax2.get_yticks():
        ax1.plot(xlim, (y, y), ls="--", color=color, lw=0.5)
    ax1.set_xlim(xlim)
    
    ylim = ax1.get_ylim()
    for x in ax3.get_xticks():
        ax1.plot((x, x), ylim, ls="--", color=color, lw=0.5)
    ax1.set_ylim(ylim)
    

    输出如下所示:

    这里的区别是现在我们在图上画线,看起来像网格线。

    【讨论】:

    • 非常感谢。但是,我将保留这个问题,看看是否有人知道为什么 grid() 在 SecondaryAxis 上不起作用。
    • 添加了为什么 SecondaryAxis.grid() 不起作用的解释,以及另一种替代解决方法。
    【解决方案2】:

    要添加 np8 的答案,您还可以使用axvline 来画线。这样做的好处是您不需要手动跟踪 y 限制:

    for x in ax2.get_xticks():
        ax1.axvline(x, color=color, zorder=-1, linestyle="--", linewidth=0.5)
    

    另请注意,您需要适当地变换 x 坐标以匹配从 ax1 到 ax2 的变换。

    另外,在我的例子中,我首先必须渲染画布才能生成刻度标签:

    fig1.canvas.draw()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-15
      • 2023-01-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多