Ruota il testo dell'asse in matplotlib in pitone


314

Non riesco a capire come ruotare il testo sull'asse X. È un timestamp, quindi quando il numero di campioni aumenta, si avvicinano sempre di più fino a quando non si sovrappongono. Vorrei ruotare il testo di 90 gradi in modo che i campioni si avvicinino, non si sovrappongano.

Di seguito è quello che ho, funziona benissimo con l'eccezione che non riesco a capire come ruotare il testo dell'asse 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')

3
Vedi questa risposta per informazioni importanti sull'allineamento delle etichette ruotate con ha(allineamento orizzontale)
— Londra,

Risposte:


513

Questo funziona per me:

plt.xticks(rotation=90)

8
Nel caso in cui qualcun altro stia usando mpld3 ed è frustrato dal fatto che nessuna di queste soluzioni funzioni. La rotazione non è supportata in mpld3.
— Beetree,

4
Punti extra per farli rimanere all'interno della figura / finestra. I miei sono metà fuori.
— Gauthier,

1
Chiamalo dopo aver tracciato. Cioè, prima ax.plot(...)poiplt.xticks(rotation=90)
— CGFoX

161

Modo semplice

Come descritto qui , esiste un metodo esistente nella matplotlib.pyplot figureclasse che ruota automaticamente le date in modo appropriato per la tua figura.

Puoi chiamarlo dopo aver tracciato i tuoi dati (ad esempio ax.plot(dates,ydata):

fig.autofmt_xdate()

Se hai bisogno di formattare ulteriormente le etichette, controlla il link sopra.

Oggetti non datetime

Come da commento di languitar , il metodo che ho suggerito per il non datetime xticksnon si aggiorna correttamente durante lo zoom, ecc. Se non è un datetimeoggetto usato come dati dell'asse x, dovresti seguire la risposta di Tommy :

for tick in ax.get_xticklabels():
    tick.set_rotation(45)

3
Questo è il modo migliore perché è conciso, opera su tick generati automaticamente esistenti e regola i margini della trama in modo che sia leggibile. Altri metodi consentono alle zecche di uscire dalla pagina, richiedendo ulteriori azioni (come plt.tight_layouts ()) per modificarle.
— EL_DON

Nel caso in cui sia stato utilizzato un localizzatore e un formatter, il metodo "altro" potrebbe interromperne l'effetto se applicato successivamente.
— languitar

73

Molte risposte "corrette" qui, ma ne aggiungerò un'altra poiché ritengo che alcuni dettagli siano lasciati fuori da molti. L'OP ha richiesto una rotazione di 90 gradi, ma cambierò a 45 gradi perché quando si utilizza un angolo diverso da zero o 90, è necessario modificare anche l'allineamento orizzontale; altrimenti le tue etichette saranno decentrate e un po 'fuorvianti (e sto indovinando molte persone che vengono qui vogliono ruotare gli assi su qualcosa di diverso da 90).

Il codice più semplice / minimo

opzione 1

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

Come accennato in precedenza, ciò potrebbe non essere desiderabile se si preferisce adottare l'approccio orientato agli oggetti.

opzione 2

Un altro modo rapido (è destinato agli oggetti data ma sembra funzionare su qualsiasi etichetta; dubiti che questo sia raccomandato comunque):

fig.autofmt_xdate(rotation=45)

fig di solito si ottiene da:

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

Orientato agli oggetti / trattare direttamente con ax

Opzione 3a

Se hai l'elenco di etichette:

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

Opzione 3b

Se vuoi ottenere l'elenco delle etichette dalla trama corrente:

# 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')

Opzione 4

Simile a sopra, ma invece scorrere manualmente.

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

Opzione 5

Usiamo ancora pyplot(as plt) qui ma è orientato agli oggetti perché stiamo cambiando la proprietà di un axoggetto specifico .

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

Opzione 6

Questa opzione è semplice, ma AFAIK non è possibile impostare l'allineamento orizzontale dell'etichetta in questo modo, quindi un'altra opzione potrebbe essere migliore se l'angolo non è 90.

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

Modifica: si parla di questo "bug" esatto e una correzione è potenzialmente prevista per v3.2.0: https://github.com/matplotlib/matplotlib/issues/13774


65

Prova pyplot.setp. Penso che potresti fare qualcosa del genere:

x = range(len(time))
plt.xticks(x,  time)
locs, labels = plt.xticks()
plt.setp(labels, rotation=90)
plt.plot(x, delay)

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

Penso di aver perso un passo prima. L'esempio modificato aiuta? Sono tutt'altro che un esperto di matplotlib, potrebbe esserci un modo migliore.
— opiethehokie,

1
Questo non sembra funzionare affatto. L'immagine (sulla mia macchina) viene completamente incasinata. linee nere su tutta l'immagine di output ... Sembra quasi un codice a barre. è molto strano.
— tMC

Quale versione di matplotlib era questa? Con 1.2.0, setp(subplot(111).get_xticklabels(), rotation=90)funziona perfettamente con il backend Qt4Agg. Nel mio caso, viene ripristinato da plt.hist(), quindi lo chiamo dopo, anche se plt.plot()non lo ripristina, quindi dovresti essere a posto.
— drevicko,

1
@tMC Con mpl 1.2.0, ho copiato il tuo codice (con alcuni dati fittizi), aggiunto locs, labels = plt.xticks() plt.setp(labels, rotation=90)poco prima plt.plot(time, delay)e ha funzionato bene.
— drevicko,

54

Appart da

plt.xticks(rotation=90)

questo è anche possibile:

plt.xticks(rotation='vertical')

Funziona, ma l'altezza della trama ha qualche problema
— Roberto Marzocchi

plt.xticks(rotation=45) plt.savefig(nomefile,dpi=150, optimize=True) plt.clf()
— Roberto Marzocchi,

49

Ho trovato un esempio simile. Ancora una volta, la parola chiave di rotazione è ... beh, è ​​la chiave.

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 ) ;

Sembra che funzioni, ma mostra il tempo in secondi dall'epoca- non il timestamp dadatetime
— tMC

32

La mia risposta è ispirata dalla risposta di cjohnson318, ma non volevo fornire un elenco di etichette codificate; Volevo ruotare le etichette esistenti:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)

2
Questo non sembra funzionare più. Non c'è alcun effetto.
— zbyszek,

31

Se si utilizza plt:

plt.xticks(rotation=90)

In caso di utilizzo di Panda o Seaborn per la trama, assumendo axcome assi per la trama:

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

Un altro modo di fare quanto sopra:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)

Tutti questi metodi sono già stati mostrati in altre risposte. Cosa aggiunge questa risposta qui?
— ImportanceOfBeingErnest

@ImportanceOfBeingErnest È pensato per aiutare coloro che usano i panda o i nati marini, e non direttamente matplotlib, per la stampa.
— Manavalan Gajapathy

for tick in ax.get_xticklabels(): tick.set_rotation(45)ha fatto il trucco per me.
— AP

30

Se si desidera applicare la rotazione sull'oggetto degli assi, si sta utilizzando il modo più semplice tick_params. Per esempio.

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

Riferimento della documentazione di Matplotlib qui .

Ciò è utile quando si ha una matrice di assi restituiti da plt.subplots, ed è più conveniente dell'uso set_xticksperché in quel caso è necessario impostare anche le etichette dei tick e anche più conveniente di quelli che si ripetono sui tick (per ovvi motivi)


1
Oltre a ciò, questa soluzione funziona anche nella funzione di stampa di Panda Dataframe poiché restituisce anche gli oggetti degli assi. Controllare qui . Funzione abbastanza utile. pd_dataframe.plot().tick_params(axis='x', labelrotation=90).
— metinsenturk,

L'unico problema con questo è che non riesco a capire come allineare orizzontalmente correttamente le etichette se uso qualcosa di simile labelrotation=30.
— getup8


3

Dipenderà da cosa stai tramando.

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)

Per i panda e i nati marini che ti danno un oggetto 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)

Se è necessario ruotare le etichette, potrebbe essere necessario modificare anche la dimensione del carattere, è possibile utilizzare font_scale=1.0per farlo.


2

Per ruotare l'etichetta dell'asse x di 90 gradi

for tick in ax.get_xticklabels():
    tick.set_rotation(45)

Mi piace quanto sia breve la tua risposta, ma ciò che hai pubblicato non è un codice Python valido. Non mi è chiaro come interpretarlo come codice Python valido.
— Dave C

1

La soluzione più semplice è usare:

plt.xticks(rotation=XX)

ma anche

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

ad es. per le date in cui ho usato la rotazione = 45 e il fondo = 0,20 ma puoi fare dei test per i tuoi dati

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.