Reputation: 3965
I recently upgraded to matplotlib
v1.5. What I started seeing is that twinx
plots started to fail to align grid lines even when I manually sets the yaxis ticks.
I'm using Anaconda v.2.4 with Python 2.7.
EDIT: 2015-11-25, as suggested by @ali_m, I submitted an ticket about this here on GitHub.
E.g:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x = [x + 0.5 for x in range(10)]
z = [(y+0.0)/10-0.004 for y in range(10)]
df1 = pd.DataFrame({'x': x})
df2 = pd.DataFrame({'z': z})
fig, ax = plt.subplots()
# plot something with ax
df1.plot(ax=ax)
# plot second dataframe on secondary y
ax2 = ax.twinx()
df2.plot(ax=ax2)
print('Before setting ax ticks (not ax2)')
print('ax ticks', ax.get_yticks())
print('ax2 ticks', ax2.get_yticks())
print('ax2 ybound', ax2.get_ybound())
# manually set the number of ticks for both axes to match
ticks = ax.get_yticks()
dis = ticks[-1] - ticks[-2]
# left axis has less ticks then right by default
for _ in range(len(ax2.get_yticks()) - len(ax.get_yticks())):
ticks = np.append(ticks, ticks[-1] + dis)
# print('ticks', ticks)
# comment out this line below to NOT set ticks
ax.yaxis.set_ticks(ticks)
print('After setting ax ticks (not ax2)')
print('ax ticks', ax.get_yticks())
print('ax2 ticks', ax2.get_yticks())
print('ax2 ybound', ax2.get_ybound())
OUTPUT:
# you can see here that the number of ticks matched for both axes.
Before setting ticks
ax ticks [ 0. 2. 4. 6. 8. 10.]
ax ybound (0.0, 10.0)
ax2 ticks [-0.2 0. 0.2 0.4 0.6 0.8 1. 1.2]
ax2 ybound (-0.20000000000000001, 1.0000000000000002)
After setting ticks
ax ticks [ 0. 2. 4. 6. 8. 10. 12. 14.]
ax ybound (0.0, 14.0)
ax2 ticks [-0.2 0. 0.2 0.4 0.6 0.8 1. 1.2]
ax2 ybound (-0.20000000000000001, 1.0000000000000002)
However, when in the plot, the right axis ax2
's last tick is not show, i.e. the maximum stops at 1.0
, rather than 1.2
as show in the print out above.
EDIT - Note that I manually set ticks for ax
, not ax2
, the problem is happening to ax2
.
Question 1: why is the last tick not show on the right axis?
EDIT: Thanks to @DilithiumMatrix & @ali_m, I now see that setting ticks doesn't update limits or bounds. However, this problem is happening to the right axis, whose limits and bounds are set automatically through df2.plot(ax=ax2)
. Perhaps someone can comment on how the logic to set limits & bounds work automatically?
Question 2: Any suggestions on how I can get the grid lines to match again?
EDIT I figured out a hack by manually setting the upper ybound
, it re-aligns the grid lines...
ax.set_ybound(upper=max(ax.get_yticks()))
ax2.set_ybound(upper=max(ax2.get_yticks()))
In fact I just tried to plot these WITHOUT manually setting the ticks you still get the same problem.
EDIT: Adding a pic to show default ax2
behaviour, without changing ax
's ticks.
Upvotes: 0
Views: 767
Reputation: 18627
I'm not sure why this behavior would just start with matplotlib v1.5, as aligning the grid lines for different axes has never been a feature (to my knowledge). It seems as though the issue you're having, however, is setting the y limits. Calling set_yticks
(which internal calls the yaxis.set_ticks
method), does not set the limits --- it just sets the 'locator' of the ticks. If you want to set the bounds of the axis, you need to call one of those methods explicitly, in this case either ax.set_ylim
or ax.set_ybound
.
Addition:
Tick marks are always really weird / difficult to mess-with. The way I tend to do things these days is to always deal with them very explicitly. Set the limits to particular values, set the ticks to particular values. Don't count on the default-defined tick-marks to be what you would naively expect.
Upvotes: 2