Comment puis-je faire pivoter xticklabels dans matplotlib afin que l'espacement entre chaque xticklabel soit égal?
Par exemple avec ce code:
import matplotlib.pyplot as plt
import numpy as np
# Data + parameters
fontsize = 20
t = np.arange(0.0, 6.0, 1)
xticklabels = ['Full', 'token emb', 'char emb', 'char LSTM',
'token LSTM', 'feed forward','ANN']
# Plotting
fig = plt.figure(1)
ax = fig.add_subplot(111)
plt.plot(t, t)
plt.xticks(range(0, len(t) + 1))
ax.tick_params(axis='both', which='major', labelsize=fontsize)
ax.set_xticklabels(xticklabels, rotation = 45)
fig.savefig('test_rotation.png', dpi=300, format='png', bbox_inches='tight')
J'obtiens:
L'espacement entre chaque xticklabel est inégal. Par exemple, l'espacement entre "Full" et "token emb" est beaucoup plus grand que l'espacement entre "feed forward" et "ANN".
J'utilise Matplotlib 2.0.0 et Python 3.5 64 bits sur Windows 7 SP1 x64 Ultimate.
Les étiquettes sont centrées à la position de la coche. Leurs boîtes de délimitation sont de largeur inégale et peuvent même se chevaucher, ce qui les rend espacées de manière inégale.
Étant donné que vous souhaitez toujours que les étiquettes soient liées à leurs graduations, la modification de l'espacement n'est pas vraiment une option.
Cependant, vous souhaiterez peut-être les aligner de sorte que le coin supérieur droit soit la référence pour leur positionnement sous la coche.
Utilisez l'argument horizontalalignment
ou ha
pour cela et définissez-le sur "right"
:
ax.set_xticklabels(xticklabels, rotation = 45, ha="right")
Il en résulte le tracé suivant:
Une alternative peut être de garder les ticklabels centrés horizontalement, mais aussi de les centrer verticalement. Cela conduit à un espacement égal mais nécessaire pour ajuster davantage leur position verticale par rapport à l'axe.
ax.set_xticklabels(xticklabels, rotation = 45, va="center", position=(0,-0.28))
Ce qui précède peut être utilisé si les graduations sont spécifiées manuellement comme dans la question (par exemple via plt.xticks
ou via ax.set_xticks
) ou si un tracé catégoriel est utilisé.
Si, au contraire, les étiquettes sont affichées automatiquement, une ne doit pas utiliser set_xticklabels
. Cela laissera généralement les étiquettes et les positions des ticks désynchronisées, car set_xticklabels
définit le formateur des axes sur FixedFormatter
, tandis que le localisateur reste le AutoLocator
automatique ou tout autre localisateur automatique.
Dans ces cas, utilisez soit plt.setp
pour définir la rotation et l'alignement des étiquettes existantes,
plt.setp(ax.get_xticklabels(), ha="right", rotation=45)
ou boucle sur eux pour définir les propriétés respectives,
for label in ax.get_xticklabels():
label.set_ha("right")
label.set_rotation(45)
Un exemple serait
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
t = np.arange("2018-01-01", "2018-03-01", dtype="datetime64[D]")
x = np.cumsum(np.random.randn(len(t)))
fig, ax = plt.subplots()
ax.plot(t, x)
for label in ax.get_xticklabels():
label.set_ha("right")
label.set_rotation(45)
plt.tight_layout()
plt.show()