Обертати текст осі в matplotlib python


313

Я не можу зрозуміти, як обертати текст на осі X. Своєю часовою позначкою, так як кількість зразків збільшується, вони все ближче і ближче, поки вони не перетинаються. Я хотів би повернути текст на 90 градусів, щоб зразки зблизилися, вони не перетиналися.

Нижче наведено те, що у мене є, воно прекрасно працює за винятком того, що я не можу зрозуміти, як обертати текст осі 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
Дивіться цю відповідь на важливі речі щодо вирівнювання повернутих міток з ha(горизонтальне вирівнювання)
LondonRob

Відповіді:


510

Це працює для мене:

plt.xticks(rotation=90)

8
У випадку, якщо хтось інший не використовує mpld3, і засмучений, що жоден із цих рішень не працює. Обертання не підтримується в mpld3.
буряк

4
Додаткові бали за те, щоб вони залишалися всередині фігури / вікна. Мої наполовину назовні.
Готьє

1
Зателефонуйте цьому після побудови графіку. Тобто, по- перше , ax.plot(...)теplt.xticks(rotation=90)
CGFoX

161

Легкий шлях

Як описано тут , у matplotlib.pyplot figureкласі існує існуючий метод, який автоматично обертає дати, відповідно до вашої фігури.

Ви можете зателефонувати на нього, після того як ви зможете побудувати свої дані (тобто ax.plot(dates,ydata):

fig.autofmt_xdate()

Якщо вам потрібно додатково відформатувати мітки, перегляньте вищенаведене посилання.

Об'єкти без дати

Згідно languitar «s коментар, метод , який я запропонував для НЕ дати і часу xticksНЕ буде коректно оновлюватися при масштабуванні і т.д. Якщо це не datetimeоб'єкт , який використовується в якості даних по осі X, ви повинні слідувати Томмі » відповідь s :

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

3
Це найкращий спосіб, оскільки він лаконічний, він працює на існуючих автоматично сформованих кліщах і коригує межі ділянки так, щоб він був читабельним. Інші методи дозволяють кліщам відійти від сторінки, вимагаючи подальших дій (наприклад, plt.tight_layouts ()) для їх коригування.
EL_DON

Якщо ви використовували локатор та формат, метод "інший" може порушити їх дію, якщо застосувати його згодом.
languitar

73

Тут є багато "правильних" відповідей, але я додам ще один, оскільки думаю, що деякі деталі залишилися без кількох. ОП попросив обертання на 90 градусів, але я зміню на 45 градусів, тому що, коли ви використовуєте кут, який не дорівнює нулю або 90, ви також повинні змінити горизонтальне вирівнювання; інакше ваші ярлики будуть нецентральними і трохи оманливими (і я здогадуюсь, що багато людей, які приїжджають сюди, хочуть повернути осі на щось, крім 90).

Найпростіший / найменший код

Варіант 1

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

Як було сказано раніше, це може бути небажаним, якщо ви краще скористаєтесь об'єктно-орієнтованим підходом.

Варіант 2

Ще один швидкий спосіб (він призначений для об’єктів дати, але, здається, працює над будь-якою міткою; хоча б сумніватися в цьому рекомендується):

fig.autofmt_xdate(rotation=45)

fig Ви зазвичай отримуєте:

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

Об'єктно-орієнтована / безпосередньо стосується ax

Варіант 3а

Якщо у вас є список міток:

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

Варіант 3b

Якщо ви хочете отримати список міток з поточного сюжету:

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

Варіант 4

Подібно до вище, але замість цього перебирайте вручну.

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

Варіант 5

Тут ми все ще використовуємо pyplot(як plt), але це орієнтоване на об'єкти, оскільки ми змінюємо властивість конкретного axоб'єкта.

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

Варіант 6

Цей варіант простий, але AFAIK ви не можете встановити горизонтальне вирівнювання мітки таким чином, щоб інший варіант міг бути кращим, якщо ваш кут не дорівнює 90.

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

Редагувати: Існує дискусія про цю точну "помилку", і виправлення потенційно призначене для v3.2.0: https://github.com/matplotlib/matplotlib/isissue/13774


65

Спробуйте pyplot.setp. Я думаю, ви могли б зробити щось подібне:

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

Я думаю, я пропустив крок раніше. Чи допомагає відредагований приклад? Я далеко не експерт з матплотлібів, але може бути кращий спосіб.
opiethehokie

1
Схоже, це зовсім не працює - зображення (на моїй машині) повністю заплуталося. чорні лінії по всьому вихідному зображенню ... Майже виглядає як штрих-код. дуже дивно.
tMC

Яка версія matplotlib була такою? З 1.2.0, setp(subplot(111).get_xticklabels(), rotation=90)чудово працює з Qt4Agg. У моєму випадку він обнуляється plt.hist(), тому я зателефоную після цього, хоча plt.plot()він не скидає його, тож вам слід добре.
drevicko

1
@tMC За допомогою mpl 1.2.0 я скопіював ваш код (з деякими фіктивними даними), додав locs, labels = plt.xticks() plt.setp(labels, rotation=90)напередодні, plt.plot(time, delay)і він працював чудово.
drevicko


49

Я придумав подібний приклад. Знову ж таки, ключове слово обертання - це ... ну, це ключове.

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

Схоже, це працює, але він показує час як секунди з епохи, а не часову datetime
позначку

32

Моя відповідь натхненна відповіддю cjohnson318, але я не хотів подавати твердо кодований список міток; Я хотів повернути існуючі мітки:

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

2
Схоже, це вже не працює. Ефекту немає.
zbyszek

31

Якщо використовується plt:

plt.xticks(rotation=90)

У разі використання панди або морського немовляти для побудови сюжету, вважаючи axосі для ділянки:

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

Ще один спосіб зробити вищезазначене:

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

Усі ці методи вже показані в інших відповідях. Що тут додає ця відповідь?
ВажливістьBeingErnest

@ImportanceOfBeingErnest Це призначено для того, щоб допомогти тим, хто використовує панди чи мореплавців, а не matplotlib безпосередньо для побудови планів.
Манавалан Гаджапатій

for tick in ax.get_xticklabels(): tick.set_rotation(45)зробив трюк для мене.
AP

30

Якщо ви хочете застосувати обертання на осі об'єкта, найпростішим способом є використання tick_params. Наприклад.

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

Тут посилання на документацію Matplotlib .

Це корисно, коли у вас є масив осей, повернутий plt.subplots, і це зручніше, ніж використовувати, set_xticksоскільки в цьому випадку вам також потрібно встановити мітки галочок, а також зручніше, ніж ті, які перебираються над кліщами (з очевидних причин)


1
На додаток до цього, це рішення також працює у графічній функції пандус даних, оскільки також повертає об'єкт осей. Перевірте тут . Досить зручна функція. pd_dataframe.plot().tick_params(axis='x', labelrotation=90).
metinsenturk

Проблема полягає лише в тому, що я не можу зрозуміти, як правильно горизонтально вирівняти етикетки, якщо використовую щось подібне labelrotation=30.
getup8


3

Це залежатиме від того, що ви плануєте.

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)

Для панд і морських новонароджених, які дають вам об'єкт Оси:

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)

Якщо вам потрібно обертати мітки, можливо, вам також знадобиться змінити розмір шрифту, ви можете використовувати це font_scale=1.0для цього.


2

Щоб повернути мітку осі x на 90 градусів

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

Мені подобається, наскільки коротка ваша відповідь, але те, що ви розмістили, не є дійсним кодом Python. Мені незрозуміло, як інтерпретувати це як дійсний код python.
Дейв C

1

Найпростішим рішенням є використання:

plt.xticks(rotation=XX)

але також

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

наприклад, для дат я використовував обертання = 45 і внизу = 0,20, але ви можете зробити тест на свої дані

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.