2

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:

Figure

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:

Final figure

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

How to move a tick's label in matplotlib?

Matplotlib log scale tick label number formatting

KR15
  • 23
  • 4

0 Answers0