Girar texto do eixo no python matplotlib

314

Não consigo descobrir como girar o texto no eixo X. É um carimbo de data / hora, assim, à medida que o número de amostras aumenta, elas se aproximam cada vez mais até se sobreporem. Eu gostaria de girar o texto 90 graus para que as amostras se aproximem e não se sobreponham.

Abaixo está o que eu tenho, funciona bem com a exceção de que não consigo descobrir como girar o texto do eixo 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
fonte
3
Veja esta resposta para coisas importantes sobre o alinhamento dos rótulos rodados com ha(Alinhar horizontal)
LondonRob

Respostas:

513

Isso funciona para mim:

plt.xticks(rotation=90)
scottlittle
fonte
8
Caso alguém mais esteja usando o mpld3, e fique frustrado por nenhuma dessas soluções funcionar. A rotação não é suportada no mpld3.
beetree 30/09/18
4
Pontos extras para fazer com que fiquem dentro da figura / janela. Os meus estão meio fora.
Gauthier
1
Chame isso após a plotagem. ax.plot(...)plt.xticks(rotation=90)
Ou
161

Jeito fácil

Conforme descrito aqui , existe um método existente na matplotlib.pyplot figureclasse que gira automaticamente as datas adequadamente para a sua figura.

Você pode chamá-lo depois de plotar seus dados (ou seja ax.plot(dates,ydata):

fig.autofmt_xdate()

Se você precisar formatar ainda mais os rótulos, verifique o link acima.

Objetos não datetime

De acordo com o comentário do languitar , o método que sugeri para não data e hora xticksnão seria atualizado corretamente ao aplicar zoom, etc. Se não for um datetimeobjeto usado como seus dados do eixo x, você deve seguir a resposta de Tommy :

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
ryanjdillon
fonte
3
Essa é a melhor maneira, pois é concisa, opera com ticks gerados automaticamente existentes e ajusta as margens da plotagem para facilitar a leitura. Outros métodos permitem que os ticks saiam da página, exigindo ações adicionais (como plt.tight_layouts ()) para ajustá-los.
EL_DON 9/09/16
Caso você tenha usado um localizador e formatador, o método "outro" poderá interromper seu efeito se aplicado posteriormente.
languitar
73

Muitas respostas "corretas" aqui, mas adicionarei mais uma, pois acho que alguns detalhes são deixados de fora de várias. O OP pediu uma rotação de 90 graus, mas vou mudar para 45 graus, porque quando você usa um ângulo que não é zero ou 90, deve alterar também o alinhamento horizontal; caso contrário, seus rótulos serão descentralizados e um pouco enganadores (e acho que muitas pessoas que vêm aqui querem girar os eixos para algo diferente de 90).

Código mais fácil / menos

Opção 1

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

Como mencionado anteriormente, isso pode não ser desejável se você preferir a abordagem orientada a objetos.

opção 2

Outra maneira rápida (destina-se a objetos de data, mas parece funcionar em qualquer rótulo; duvide que isso seja recomendado):

fig.autofmt_xdate(rotation=45)

fig você normalmente obteria de:

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

Orientado a objeto / Lidando diretamente com ax

Opção 3a

Se você tiver a lista de etiquetas:

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

Opção 3b

Se você deseja obter a lista de etiquetas do gráfico atual:

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

Opção 4

Semelhante ao anterior, mas alterna manualmente.

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

Opção 5

Ainda usamos pyplot(as plt) aqui, mas é orientado a objetos, porque estamos alterando a propriedade de um axobjeto específico .

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

Opção 6

Essa opção é simples, mas no AFAIK você não pode definir o alinhamento horizontal da etiqueta dessa maneira, assim outra opção pode ser melhor se o seu ângulo não for 90.

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

Editar: há uma discussão sobre esse "bug" exato e uma correção está potencialmente prevista para v3.2.0: https://github.com/matplotlib/matplotlib/issues/13774

getup8
fonte
65

Tente pyplot.setp. Eu acho que você poderia fazer algo assim:

x = range(len(time))
plt.xticks(x,  time)
locs, labels = plt.xticks()
plt.setp(labels, rotation=90)
plt.plot(x, delay)
opiethehokie
fonte
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 12/06
Acho que perdi um passo antes. O exemplo editado ajuda? No entanto, estou longe de ser um especialista em matplotlib, poderia haver uma maneira melhor.
Opithehokie
1
Isso parece não funcionar: a imagem (na minha máquina) fica completamente bagunçada. linhas pretas em toda a imagem de saída ... Quase parece um código de barras. é muito estranho.
tMC 12/06
Qual versão do matplotlib era essa? Com o 1.2.0, setp(subplot(111).get_xticklabels(), rotation=90)funciona bem com o back-end Qt4Agg. No meu caso, ele é redefinido plt.hist(), então eu ligo depois, embora plt.plot()não o redefina, então você deve ficar bem.
drevicko
1
@tMC Com o mpl 1.2.0, copiei seu código (com alguns dados fictícios), adicionei locs, labels = plt.xticks() plt.setp(labels, rotation=90)pouco antes plt.plot(time, delay)e funcionou bem.
28413 drevicko
54

Appart from

plt.xticks(rotation=90)

isso também é possível:

plt.xticks(rotation='vertical')
Mateus
fonte
Funciona, mas a altura da trama tem algum problema
Roberto Marzocchi
plt.xticks(rotation=45) plt.savefig(nomefile,dpi=150, optimize=True) plt.clf()
Roberto Marzocchi
49

Eu vim com um exemplo semelhante. Mais uma vez, a palavra-chave rotação é ... bem, é a chave.

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
fonte
Isto olha como ele funciona, mas ele mostra o tempo como segundos desde a epoch- não o timestamp dedatetime
TMC
32

Minha resposta é inspirada na resposta de cjohnson318, mas eu não queria fornecer uma lista codificada de rótulos; Eu queria girar os rótulos existentes:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Tommy
fonte
2
Isso parece não funcionar mais. Não há nenhum efeito.
precisa saber é
31

Se estiver usando plt:

plt.xticks(rotation=90)

No caso de usar pandas ou seaborn na plotagem, assumindo axcomo eixos para a plotagem:

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

Outra maneira de fazer o acima:

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Manavalan Gajapathy
fonte
Todos esses métodos já foram mostrados em outras respostas. O que esta resposta está adicionando aqui?
ImportanceOfBeingErnest
@ImportanceOfBeingErnest Destina-se a ajudar aqueles que usam pandas ou transatlânticos, e não o matplotlib diretamente, na plotagem.
Manavalan Gajapathy
for tick in ax.get_xticklabels(): tick.set_rotation(45)fez o truque para mim.
AP
30

Se você deseja aplicar a rotação no objeto de eixos, a maneira mais fácil é usar tick_params. Por exemplo.

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

Referência da documentação do Matplotlib aqui .

Isso é útil quando você tem uma matriz de eixos retornada plt.subplotse é mais conveniente do que usar, set_xticksporque nesse caso você também precisa definir os rótulos dos ticks e também mais conveniente que aqueles que iteram nos ticks (por razões óbvias)

Kiril
fonte
1
Além disso, essa solução também funciona na função plot do dataframe do pandas, pois também retorna o objeto de eixos. Confira aqui . Função bastante útil. pd_dataframe.plot().tick_params(axis='x', labelrotation=90).
metinsenturk
O único problema com isso é que não consigo descobrir como alinhar horizontalmente os rótulos corretamente se usar algo parecido labelrotation=30.
getup8
8
import pylab as pl
pl.xticks(rotation = 90)
Ishan Tomar
fonte
3

Vai depender do que você está 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)

Para pandas e transatlânticos que oferecem um objeto 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 você precisar rotacionar etiquetas, também poderá precisar alterar o tamanho da fonte, font_scale=1.0para fazer isso.

Isac Junior
fonte
2

Para girar o rótulo do eixo x para 90 graus

for tick in ax.get_xticklabels():
    tick.set_rotation(45)
Mudit
fonte
Gosto da resposta curta, mas o que você postou não é um código Python válido. Não está claro para mim como interpretá-lo como código python válido.
Dave C
1

A solução mais simples é usar:

plt.xticks(rotation=XX)

mas também

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

por exemplo, para datas que usei rotação = 45 e inferior = 0,20, mas você pode fazer alguns testes para seus dados

Roberto Marzocchi
fonte