Поворот текста оси в python matplotlib


315

Я не могу понять, как повернуть текст по оси 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

Ответы:


513

Это работает для меня:

plt.xticks(rotation=90)

8
В случае, если кто-то еще использует mpld3, и разочарован тем, что ни одно из этих решений не работает. Вращение не поддерживается в mpld3.
свекла

4
Дополнительные очки для того, чтобы они оставались внутри фигуры / окна. Мои наполовину снаружи.
Готье

1
Назовите это после прорисовки. ax.plot(...)plt.xticks(rotation=90)
То

161

Простой способ

Как описано здесь , в matplotlib.pyplot figureклассе есть существующий метод, который автоматически поворачивает даты в соответствии с вашей цифрой.

Вы можете позвонить после того, как вы нанесете свои данные (то есть ax.plot(dates,ydata):

fig.autofmt_xdate()

Если вам нужно отформатировать метки, перейдите по ссылке выше.

Объекты, не относящиеся к дате

В соответствии с комментарием Лангитара , метод, который я предложил для не-datetime xticks, не будет корректно обновляться при масштабировании и т. Д. Если это не datetimeобъект, используемый в качестве данных оси X, вы должны следовать ответу Томми :

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

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

В случае, если вы использовали локатор и форматер, «другой» метод может нарушить их действие при последующем применении.
17

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

Вариант 3б

Если вы хотите получить список меток с текущего графика:

# 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/issues/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

Я думаю, что пропустил шаг раньше. Поможет ли отредактированный пример? Я далеко не эксперт по matplotlib, хотя, может быть, есть лучший способ.
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 ) ;

Это выглядит , как это работает, но это показывает время в секундах с момента epoch- не метка времени изdatetime
TMC

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)

Все эти методы были показаны уже в других ответах. Что этот ответ добавляет сюда?
Важное значение

@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
В дополнение к этому, это решение также работает в функции plot pandas dataframe, поскольку оно также возвращает объект axes. Проверьте здесь . Довольно удобная функция. 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.
Дэйв С

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.