6

I'm trying to rotate the x axis labels on the subplots created in this question.

Unfortunately, my modification to the example code here seems to have no effect on the x axis labels:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)

par1 = host.twinx()
par2 = host.twinx()

offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
                                    axes=par2,
                                    offset=(offset, 0))

par1.axis["right"].toggle(all=True)
par2.axis["right"].toggle(all=True)

host.set_xlim(0, 2)
host.set_ylim(0, 2)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

par1.set_ylim(0, 4)
par2.set_ylim(1, 65)

host.legend()

host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color(p2.get_color())
par2.axis["right"].label.set_color(p3.get_color())

plt.xticks(rotation = 45) #<- The only change from the example

plt.draw()
plt.show()  

gives un-rotated x axis labels in:

Output

Although I've shown the plt.xticks(rotation = 45), I've also tried other ways that work with "conventional" matplotlib plots without success. Does anyone know if there is a way to do this, or am I just dealing with too much of a niche case? Maybe I should just figure out a way to live with using sub plots and no parasite axes?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Alex S
  • 4,726
  • 7
  • 39
  • 67
  • It seems the problem is using `AA.Axes` in `host_subplot`. Without this, the rotation works as expected (see also https://stackoverflow.com/questions/28275681/aligning-rotating-text-labels-on-x-axis-in-matplotlib-with-3-plots). Might be worth submitting a bug request (I'm using matplotlib 2.2.2 and still failing in this) – Ed Smith May 30 '18 at 07:39
  • It seems the axis labels are redefined by using parasitic axis, so something like `host.axis["bottom"].axis.set_ticklabels(labels, rotation=45)` should be a solution, although even this doesn't work for me. – Ed Smith May 30 '18 at 08:05

1 Answers1

5

There are two ways to produce parasite axes:

Here you are using the first approach, which may be a bit unintuitive due to it using the special axes provided by the axisartist toolkit.

Solution 1:

Use the usual subplots approach for which all the usual ways of rotating ticklabels work just fine, e.g.

plt.setp(ax.get_xticklabels(), rotation=90)

Solution 2:

In case you want to stick with the mpl_toolkits approach you need to obtain the ticklabels from the axis via axis["right"].major_ticklabels,

plt.setp(par2.axis["bottom"].major_ticklabels, rotation=-135)
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • 1
    Solution 2 with `plt.setp(host.axis["bottom"].major_ticklabels, rotation=45)` does what the OP wants. – Ed Smith May 30 '18 at 08:42
  • @EdSmith Both solutions are solutions to the problem, hence the name. – ImportanceOfBeingErnest May 30 '18 at 08:48
  • both work, but sol 2 is the simplest with OPs existing code for bottom axis. Even using `multiple_yaxis_with_spines` to generate the plot, rotation doesn't seem to work with `plt.xticks`. The key seems to be using `plt.setp` in both cases as `set_ticklabels` does not work directly. – Ed Smith May 30 '18 at 12:50
  • @EdSmith The problem with `plt.whatever` is always that it applies to the currently active axes, so one would need to make the one to rotate the labels for active first. `set_ticklabels` should work out of the box. Solution 2 may be easiest to implement given the existing code, but it might cause more trouble in the long run when other methods also fail for the special axes in use. Using the standard matplotlib axes makes it much easier to find appropriate solutions. – ImportanceOfBeingErnest May 30 '18 at 13:04
  • Excellent, thank you. I used Solution 2, but in the answer it rotates one of the y axes, while I was trying to rotate the x axis. The same idea works, I just change it to `plt.setp(host.axis["bottom"].major_ticklabels, rotation=90)`. – Alex S May 30 '18 at 15:33