How To Put Grid Lines From The Secondary Axis Behind The Primary Plot?
Solution 1:
Your desired drawing order is (first is most to the back)
- grid for axes
- grid for twin axes
- plot in axes
- plot in twin axes
However this is not possible as seen by the comment
you can't interleave the drawing orders of artists from one Axes with those from another
What this means is that you need 4 axes instead of two.
- axes for grid of primary y scale
- axes for grid of secondary y scale
- axes for plot on primary y scale
- axes for plot on secondary y scale
This could look like this:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
foo = np.random.randn(1000)
fig, ax1a = plt.subplots() # ax1a for the histogram grid
ax2a = ax1a.twinx() # ax2a for the cumulative step grid
ax1b = ax1a.twinx() # ax1b for the histogram plot
ax2b = ax1a.twinx() # ax2a for the cumulative step plot# Link the respective y-axes for grid and plot
ax1a.get_shared_y_axes().join(ax1a, ax1b)
ax2a.get_shared_y_axes().join(ax2a, ax2b)
# Remove ticks and labels and set which side to label
ticksoff = dict(labelleft=False, labelright=False, left=False, right=False)
ax1a.tick_params(axis="y", **ticksoff)
ax2a.tick_params(axis="y", **ticksoff)
ax1b.tick_params(axis="y", labelleft=True, labelright=False, left=True, right=False)
ax2b.tick_params(axis="y", labelleft=False, labelright=True, left=False, right=True)
# Spines offfor ax in [ax1a, ax2a, ax1b]:
for k,v in ax.spines.items():
v.set_visible(False)
ax1b.hist(foo, bins=50)
ax2b.hist(
foo, bins=50, density=True, cumulative=True, histtype="step", color="tab:orange"
)
ax1a.grid()
ax2a.grid()
plt.show()
Solution 2:
There is already an accepted and working answer, but I think there's another way of solving this, while improving the aesthetics a little, too:
- don't draw the grid for
ax2
- use
ax.set_ylim()
andax.set_yticks()
to manually specify the range and ticks on the first y-axis, so that the ticks line up with the ones onax2
. That way there's no need for a second set of gridlines, and the graph becomes less visually busy.
In the example above, you could do this in the following way:
ax2.set_ylim(0.0, 1.05)
ax2.set_yticks(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)
ax.set_ylim(0.0, 70*1.05)
ax.set_yticks(0, 14, 28, 42, 56, 70)
ax.grid(both)
ax.set_axisbelow(True)
Of course, this may work better or worse depending on the actual numbers, and in the example I moved to non-whole numbers. Using ticks at 15, 30 ... could have worked, or rescaling either the second y-axis to go up to 140 or the first one to go up to 100, but there's no ideal solution. Automating this method would of course be hard -- but I do use it sometimes if I need to make good-looking graphs for a specific dataset, where spending the time to tweak it is justified.
Post a Comment for "How To Put Grid Lines From The Secondary Axis Behind The Primary Plot?"