Faire pivoter le texte de l'axe dans python matplotlib

315

Je ne peux pas comprendre comment faire pivoter le texte sur l'axe X. C'est un horodatage, donc à mesure que le nombre d'échantillons augmente, ils se rapprochent de plus en plus jusqu'à ce qu'ils se chevauchent. Je voudrais faire pivoter le texte de 90 degrés afin que les échantillons se rapprochent, ils ne se chevauchent pas.

Ci-dessous ce que j'ai, cela fonctionne bien à l'exception que je ne peux pas comprendre comment faire pivoter le texte de l'axe X.

import sys

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import datetime

font = {'family' : 'normal',
        'weight' : 'bold',
        'size'   : 8}

matplotlib.rc('font', **font)

values = open('stats.csv', 'r').readlines()

time = [datetime.datetime.fromtimestamp(float(i.split(',')[0].strip())) for i in values[1:]]
delay = [float(i.split(',')[1].strip()) for i in values[1:]]

plt.plot(time, delay)
plt.grid(b='on')

plt.savefig('test.png')
tMC
la source
3
Voir cette réponse pour des informations importantes sur l'alignement des étiquettes pivotées avec ha(alignement horizontal)
LondonRob

Réponses:

513

Cela fonctionne pour moi:

plt.xticks(rotation=90)
scottlittle
la source
8
Dans le cas où quelqu'un d'autre utilise mpld3 et est frustré qu'aucune de ces solutions ne fonctionne. La rotation n'est pas prise en charge dans mpld3.
beetree
4
Points supplémentaires pour les faire rester à l'intérieur de la figure / fenêtre. Les miens sont à moitié dehors.
Gauthier
1
Appelez cela après avoir comploté. À savoir, d' abord , ax.plot(...)puisplt.xticks(rotation=90)
CGFoX
161

Moyen facile

Comme décrit ici , il existe une méthode existante dans la matplotlib.pyplot figureclasse qui fait automatiquement pivoter les dates de manière appropriée pour votre figure.

Vous pouvez l'appeler après avoir tracé vos données (par exemple ax.plot(dates,ydata):

fig.autofmt_xdate()

Si vous avez besoin de formater davantage les étiquettes, consultez le lien ci-dessus.

Objets non datetime

Selon le commentaire de Languitar , la méthode que j'ai suggérée pour non-datetime xticksne se mettrait pas à jour correctement lors du zoom, etc. Si ce n'est pas un datetimeobjet utilisé comme données de votre axe X, vous devriez suivre la réponse de Tommy :

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
ryanjdillon
la source
3
C'est le meilleur moyen car il est concis, il fonctionne sur les ticks générés automatiquement et il ajuste les marges du tracé pour qu'il soit lisible. D'autres méthodes laissent les graduations disparaître de la page, nécessitant une action supplémentaire (comme plt.tight_layouts ()) pour les ajuster.
EL_DON
Dans le cas où vous avez utilisé un localisateur et un formateur, la méthode "autre" peut casser leur effet si elle est appliquée par la suite.
languitar
73

Beaucoup de réponses «correctes» ici, mais j'en ajouterai une de plus car je pense que certains détails sont laissés de côté. L'OP a demandé une rotation de 90 degrés, mais je vais passer à 45 degrés car lorsque vous utilisez un angle qui n'est pas nul ou 90, vous devez également modifier l'alignement horizontal; sinon vos étiquettes seront décentrées et un peu trompeuses (et je suppose que beaucoup de gens qui viennent ici veulent faire pivoter les axes vers autre chose que 90).

Code le plus facile / le moins

Option 1

plt.xticks(rotation=45, ha='right')

Comme mentionné précédemment, cela peut ne pas être souhaitable si vous préférez adopter l'approche orientée objet.

Option 2

Un autre moyen rapide (il est destiné aux objets de date mais semble fonctionner sur n'importe quelle étiquette; doute que cela soit recommandé cependant):

fig.autofmt_xdate(rotation=45)

fig vous obtiendrez généralement de:

  • fig = plt.figure()
  • fig, ax = plt.subplots()
  • fig = ax.figure

Orienté objet / Traiter directement avec ax

Option 3a

Si vous avez la liste des étiquettes:

labels = ['One', 'Two', 'Three']
ax.set_xticklabels(labels, rotation=45, ha='right')

Option 3b

Si vous souhaitez obtenir la liste des étiquettes du tracé actuel:

# Unfortunately you need to draw your figure first to assign the labels,
# otherwise get_xticklabels() will return empty strings.
plt.draw()
ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha='right')

Option 4

Similaire à ci-dessus, mais parcourez manuellement à la place.

for label in ax.get_xticklabels():
  label.set_rotation(45)
  label.set_ha('right')

Option 5

Nous utilisons toujours pyplot(as plt) ici, mais il est orienté objet car nous modifions la propriété d'un axobjet spécifique .

plt.setp(ax.get_xticklabels(), rotation=45, ha='right')

Option 6

Cette option est simple, mais AFAIK vous ne pouvez pas définir l'alignement horizontal de l'étiquette de cette façon, une autre option pourrait donc être meilleure si votre angle n'est pas de 90.

ax.tick_params(axis='x', labelrotation=45)

Edit: il y a une discussion sur ce "bug" exact et un correctif est potentiellement prévu pour v3.2.0: https://github.com/matplotlib/matplotlib/issues/13774

getup8
la source
65

Essayez pyplot.setp. Je pense que vous pourriez faire quelque chose comme ça:

x = range(len(time))
plt.xticks(x,  time)
locs, labels = plt.xticks()
plt.setp(labels, rotation=90)
plt.plot(x, delay)
opiethehokie
la source
2
Traceback (most recent call last): File "plotter.py", line 23, in <module> plt.setp(time, rotation=90) File "/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py", line 183, in setp ret = _setp(*args, **kwargs) File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 1199, in setp func = getattr(o, funcName) AttributeError: 'datetime.datetime' object has no attribute 'set_rotation'
tMC
Je pense que j'ai raté une étape plus tôt. L'exemple édité est-il utile? Je suis loin d'être un expert en matplotlib, il pourrait y avoir une meilleure solution.
opiethehokie
1
Cela ne semble pas fonctionner du tout - L'image (sur ma machine) est complètement foirée. des lignes noires partout sur l'image de sortie ... ressemble presque à un code à barres. c'est très étrange.
tMC
De quelle version de matplotlib s'agissait-il? Avec 1.2.0, setp(subplot(111).get_xticklabels(), rotation=90)fonctionne très bien avec le backend Qt4Agg. Dans mon cas, il est réinitialisé par plt.hist(), donc je l'appelle après, mais plt.plot()ne le réinitialise pas, donc vous devriez être ok.
drevicko
1
@tMC Avec mpl 1.2.0, j'ai copié votre code (avec des données factices), ajouté locs, labels = plt.xticks() plt.setp(labels, rotation=90)juste avant plt.plot(time, delay)et cela a bien fonctionné.
drevicko
54

Appart de

plt.xticks(rotation=90)

c'est aussi possible:

plt.xticks(rotation='vertical')
Matthieu
la source
Cela fonctionne, mais la hauteur de l'intrigue a un problème
Roberto Marzocchi
plt.xticks(rotation=45) plt.savefig(nomefile,dpi=150, optimize=True) plt.clf()
Roberto Marzocchi
49

J'ai trouvé un exemple similaire. Encore une fois, le mot-clé rotation est ... eh bien, c'est la clé.

from pylab import *
fig = figure()
ax = fig.add_subplot(111)
ax.bar( [0,1,2], [1,3,5] )
ax.set_xticks( [ 0.5, 1.5, 2.5 ] )
ax.set_xticklabels( ['tom','dick','harry'], rotation=45 ) ;
cjohnson318
la source
Il semble que cela fonctionne, mais il affiche le temps en secondes depuis l'époque - pas l'horodatage dedatetime
tMC
32

Ma réponse est inspirée de la réponse de cjohnson318, mais je ne voulais pas fournir une liste codée en dur d'étiquettes; Je voulais faire pivoter les étiquettes existantes:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Tommy
la source
2
Cela ne semble plus fonctionner. Il n'y a aucun effet.
zbyszek
31

Si vous utilisez plt:

plt.xticks(rotation=90)

En cas d'utilisation de pandas ou d'ours marins pour tracer, en supposant axcomme axes pour la parcelle:

ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

Une autre façon de faire ce qui précède:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Manavalan Gajapathy
la source
Toutes ces méthodes ont déjà été présentées dans d'autres réponses. Qu'est-ce que cette réponse ajoute ici?
ImportanceOfBeingErnest
@ImportanceOfBeingErnest Il est destiné à aider ceux qui utilisent des pandas ou des mers, et non pas directement matplotlib, pour le traçage.
Manavalan Gajapathy
for tick in ax.get_xticklabels(): tick.set_rotation(45)a fait l'affaire pour moi.
AP
30

Si vous souhaitez appliquer une rotation sur l'objet axes, la méthode la plus simple consiste à utiliser tick_params. Par exemple.

ax.tick_params(axis='x', labelrotation=90)

Référence de la documentation de Matplotlib ici .

Ceci est utile lorsque vous avez un tableau d'axes tel que renvoyé par plt.subplots, et c'est plus pratique que d'utiliser set_xtickscar dans ce cas, vous devez également définir les étiquettes de tick, et aussi plus pratique que celles qui itèrent sur les ticks (pour des raisons évidentes)

kiril
la source
1
En plus de cela, cette solution fonctionne également dans la fonction de tracé de pandas dataframe car elle retourne également les objets haches. Vérifiez ici . Fonction très pratique. pd_dataframe.plot().tick_params(axis='x', labelrotation=90).
metinsenturk
Le seul problème avec ceci est que je ne peux pas comprendre comment aligner horizontalement les étiquettes correctement si vous utilisez quelque chose comme labelrotation=30.
getup8
8
import pylab as pl
pl.xticks(rotation = 90)
Ishan Tomar
la source
3

Cela dépendra de ce que vous complotez.

import matplotlib.pyplot as plt

 x=['long_text_for_a_label_a',
    'long_text_for_a_label_b',
    'long_text_for_a_label_c']
y=[1,2,3]
myplot = plt.plot(x,y)
for item in myplot.axes.get_xticklabels():
    item.set_rotation(90)

Pour les pandas et les mers qui vous donnent un objet Axes:

df = pd.DataFrame(x,y)
#pandas
myplot = df.plot.bar()
#seaborn 
myplotsns =sns.barplot(y='0',  x=df.index, data=df)
# you can get xticklabels without .axes cause the object are already a 
# isntance of it
for item in myplot.get_xticklabels():
    item.set_rotation(90)

Si vous devez faire pivoter les étiquettes, vous devrez peut-être également modifier la taille de la police, vous pouvez utiliser font_scale=1.0pour cela.

Isac Junior
la source
2

Pour faire pivoter l'étiquette de l'axe des x à 90 degrés

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Mudit
la source
J'aime la brièveté de votre réponse, mais ce que vous avez publié n'est pas du code Python valide. Il n'est pas clair pour moi comment l'interpréter comme un code python valide.
Dave C
1

La solution la plus simple consiste à utiliser:

plt.xticks(rotation=XX)

mais aussi

# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=X.XX)

par exemple pour les dates j'ai utilisé rotation = 45 et bas = 0,20 mais vous pouvez faire un test pour vos données

Roberto Marzocchi
la source