I need some help in order to rotate a secondary yticks label because the following figure below will be presented like a horizontal barplot so I need to rotate all xtick and yticks label at the end. Finally the entire figure will be 90° rotated at the end for presentation.
Here is the code that I used which was inspired by: How to plot secondary_y in log scale in pyplot
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111)
ax2 = ax.twinx()
x = ["Cat1", "Cat2", "Cat3", "Cat4", "Cat5", "Cat6"]
y = np.random.randint(1, 4000, size=6)
y2 = np.random.randint(1,10000, size=6)
ax.bar(x, y, color = "r", edgecolor = "k", linewidth = 2)
ax2.plot(x, y2, "-o", color = "k")
ax2.set_yscale("log")
ax.set_ylabel("Score 1")
ax2.set_ylabel("Score 2")
plt.tight_layout()
for tick in ax.get_xticklabels():
tick.set_rotation(90)
for tick in ax.get_yticklabels():
tick.set_rotation(90)
plt.show();
And this is the figure that I obtained:
I have tried to use:
for tick in ax2.get_yticklabels():
tick.set_rotation(90)
But unfortunately, it did not work. Can you provide some help please ?
Solution:
I have just found one of the (many I guess) solution, see below:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
import matplotlib.ticker as ticker
import matplotlib.transforms
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111)
ax2 = ax.twinx()
x = ["Cat1", "Cat2", "Cat3", "Cat4", "Cat5", "Cat6"]
y = np.random.randint(1, 4000, size=6)
y2 = np.random.randint(1,10000, size=6)
ax.bar(x, y, color = "r", edgecolor = "k", linewidth = 2)
ax2.plot(x, y2, "-o", color = "k")
ax2.set_yscale("log")
### Also work with plt.setp so you can choose between that or ax.tick_params (see below: comment code)
plt.setp(ax2.yaxis.get_minorticklabels(), rotation=90)
plt.setp(ax2.yaxis.get_majorticklabels(), rotation=90)
plt.setp(ax.xaxis.get_majorticklabels(), rotation=90)
plt.setp(ax.yaxis.get_majorticklabels(), rotation=90)
#ax.tick_params(axis="x", rotation=90)
#ax2.tick_params(axis="y", which="both", rotation=90)
#ax.tick_params(axis="y", rotation=90)
# Create offset transform by 10 points in y direction for minor and major tick label of log scale
dx = 4/72 #to adjust if necessary
dy = 12/72 #to adjust if necessary
offset = matplotlib.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels (minor and major)
for label in ax2.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset)
for label in ax2.yaxis.get_minorticklabels():
label.set_transform(label.get_transform() + offset)
# Same for ax.yaxis.get_majorticklabels() to ajust position
dx_2 = 0/72 #to adjust if necessary
dy_2 = 8/72 #to adjust if necessary
offset_2 = matplotlib.transforms.ScaledTranslation(dx_2, dy_2, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels
for label in ax.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset_2)
ax.set_ylabel("Score 1")
ax2.set_ylabel("Score 2")
plt.tight_layout()
plt.show();
And this is the figure that I obtained:
The problem was that I did not know that when I transform the second axis into log scale, it creates two different ticks: minor ticks and major ticks. That's why we must use function involving both such as get_minorticklabels()
and get_majorticklabels()
and change parameters according to what we want to do (a rotation here). Therefore, I use those functions with plt.setp()
(see https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.setp.html) but tick_params()
(add in comment of the code) can do the job too in my case.
Finally, when all tick labels were rotated by 90°. I had a new issue which was that all my yaxis labels were not centered in front of the tick (small shift present). One of the solution is present below:
# Create offset transform by 12 points in y direction and 4 in x direction for minor and major tick label of log scale
dx = 4/72
dy = 12/72
offset = matplotlib.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels (major and minor if necessary).
for label in ax2.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset)
for label in ax2.yaxis.get_minorticklabels():
label.set_transform(label.get_transform() + offset)
Three topics were important to understand what was the problem and finally to find solutions:
Rotate minor ticks in matplotlib