Xavier
Xavier

Reputation: 87

Draw grid line on SecondaryAxis - Matplotlib

The question

I am trying to draw grid lines from the ticks of my SecondaryAxis with

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

nothing shows up on the figure, I believe I am in the same situation as for Format SecondaryAxis ticklabels Matplotlib, aren't I ?

However, does anybody have a workaround for the issue without reversing the scales ? I mean by reversing the scale is to have the percentages scale on the main axis and the normal scale on the secondary axis.

The full code

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='--')

The output

plot without the grid lines

Upvotes: 6

Views: 1700

Answers (2)

mghansen256
mghansen256

Reputation: 11

To add on np8's answer, you can also use axvline to draw the lines. This has the advantage that you do not need to keep track of the y limits manually:

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

Note also that you will need to appropriately transform the x-coordinate to match the transform you do from ax1 to ax2.

Also, in my case I first had to render the canvas in order for the tick labels to be generated:

fig1.canvas.draw()

Upvotes: 1

Niko Fohr
Niko Fohr

Reputation: 33840

I did some digging on this topic, and opened an issue on GitHub. Here's what I found out:

  • The SecondaryAxis is "quite new thing", added in matplotlib 3.1.0. (May 2019). Even the v.3.3.3 docs say that the secondary_xaxis() method is experimental.
  • The SecondaryAxis inherits from _AxesBase, which is an "implementation detail". It is not supposed (as of v.3.3.3) to work as Axes object, and the SecondaryAxis.grid() is not supposed to draw anything (like _AxesBase.grid() does). Although, I agree it is misleading that there is a non-working method.
  • Therefore, at the time of writing, .grid() is only assumed to work on primaxy axes.

Making the blue axis primary

  • Since .grid() only works on non-secondary axis, you make the primary axis blue, and move it to top & right.

Code

# 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)

example

Adding grid lines manually

You could add the grid lines also manually, like this

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)

The output would look like this:

enter image description here

The difference here is now we draw lines on the figure which look like the grid lines.

Upvotes: 6

Related Questions