Изменить текст метки

216

Я хочу внести некоторые изменения в несколько выбранных меток на графике.

Например, если я делаю:

label = axes.yaxis.get_major_ticks()[2].label
label.set_fontsize(size)
label.set_rotation('vertical')

размер шрифта и ориентация метки галочки изменены.

Однако, если попробовать:

label.set_text('Foo')

метка галочки не изменяется. Также если я сделаю:

print label.get_text()

ничего не напечатано.

Вот еще странность. Когда я попробовал это:

 from pylab import *
 axes = figure().add_subplot(111)
 t = arange(0.0, 2.0, 0.01)
 s = sin(2*pi*t)
 axes.plot(t, s)
 for ticklabel in axes.get_xticklabels():
     print ticklabel.get_text()

Печатаются только пустые строки, но график содержит метки, помеченные как «0.0», «0.5», «1.0», «1.5» и «2.0».

Конфискатор
источник
Можете ли вы предоставить участок, который вы использовали для получения этикетки?
Клаудио
Вы получаете пустые ярлыки, потому что вы еще не нарисовали холст. Если вы позвоните, draw()прежде чем пытаться распечатать этикетки, вы получите то, что ожидаете. Установка отдельных меток тиков, к сожалению, сложнее (происходит то, что локатор и форматировщик тиков не были сброшены, и они переопределяют вещи, когда вы set_text). Я добавлю пример чуть позже, если кто-то не побьет меня. Хотя сейчас мне нужно сесть на автобус.
Джо Кингтон
@JoeKington: Отлично! С нетерпением жду вашего исправления.
репортер
@repoman - Ну, кажется, я говорил немного раньше. То, что я имел в виду, работает для более старых версий matplotlib, но не для последней версии. Мне нужно больше копать. При этом, это не должно быть так сложно, как это ...
Джо Кингтон

Ответы:

298

Предостережение: если тиклэйблы уже не установлены в строку (как это обычно имеет место, например, в блокпосте), это не будет работать с любой версией matplotlib, более новой, чем 1.1.0. Если вы работаете с текущим мастером github, это не сработает. Я еще не уверен, в чем проблема ... Это может быть непреднамеренное изменение, а может и нет ...

Обычно вы делаете что-то вроде этого:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# We need to draw the canvas, otherwise the labels won't be positioned and 
# won't have values yet.
fig.canvas.draw()

labels = [item.get_text() for item in ax.get_xticklabels()]
labels[1] = 'Testing'

ax.set_xticklabels(labels)

plt.show()

введите описание изображения здесь

Чтобы понять причину, по которой вам нужно прыгать через столько обручей, вам нужно немного больше понять, как структурирован matplotlib.

Matplotlib сознательно избегает «статического» позиционирования тиков и т. Д., Если это явно не указано. Предполагается, что вы захотите взаимодействовать с сюжетом, и поэтому границы сюжета, отметки, метки и т. Д. Будут динамически изменяться.

Поэтому вы не можете просто установить текст данной метки. По умолчанию он сбрасывается локатором и форматером оси каждый раз при построении графика.

Однако, если локаторы и форматеры установлены как статические ( FixedLocatorи FixedFormatter, соответственно), метки галочек остаются прежними.

Это то, что set_*ticklabelsили ax.*axis.set_ticklabelsделает.

Надеемся, что это делает более понятным, почему изменение индивидуальной метки тика немного запутано.

Часто, что вы действительно хотите сделать, это просто аннотировать определенную позицию. В этом случае, посмотрите annotateвместо этого.

Джо Кингтон
источник
10
это не похоже на работу с текущей версией (1.20)!
Эндрю Джаффе
1
Если тиклбэки уже установлены в строку, как, например, в блокпосте, это все еще работает. Это может быть очевидно, но поскольку первая строка ответа такова, что он не работает с более новыми версиями matplotlib, пользователи могут полностью его пропустить (я это сделал изначально). Может быть, кратко упомянуть об этом.
Joelostblom
2
я думаю, что вы можете сократить его до plt.gca (). set_xticklabels (ярлыки)
alexey
Что, если я хочу, чтобы вес шрифта «тестирования» был таким, в boldто время как другие используют вес шрифта слова «легкий». Есть ли способ сделать это?
Стивен
1
для тех, кто использует это в ноутбуке Jupyter, может быть полезно отметить, что fig.canvas.draw()это крайне важно
wander95
96

Можно также сделать это с pylab и xticks

import matplotlib
import matplotlib.pyplot as plt
x = [0,1,2]
y = [90,40,65]
labels = ['high', 'low', 37337]
plt.plot(x,y, 'r')
plt.xticks(x, labels, rotation='vertical')
plt.show()

http://matplotlib.org/examples/ticks_and_spines/ticklabels_demo_rotation.html

rafaelvalle
источник
Это простое решение и работает с pyplot 1.5.1. Это должно быть проголосовано.
Wordsmith
Хотя этот вопрос не задавался этим вопросом, я ценю, что этот пример позволяет вам установить местоположение галочек одновременно с изменением их меток.
экларк
Из современных документов matplotlib : «pylab устарел, и его использование настоятельно не рекомендуется из-за загрязнения пространства имен. Вместо этого используйте pyplot».
Натаниэль Джонс
93

В более новых версиях matplotlib, если вы не устанавливаете метки тиков с кучей strзначений, они используются ''по умолчанию (а когда график отрисовывается, метки являются просто значениями тиков). Зная это, чтобы получить желаемый результат, потребуется что-то вроде этого:

>>> from pylab import *
>>> axes = figure().add_subplot(111)
>>> a=axes.get_xticks().tolist()
>>> a[1]='change'
>>> axes.set_xticklabels(a)
[<matplotlib.text.Text object at 0x539aa50>, <matplotlib.text.Text object at 0x53a0c90>, 
<matplotlib.text.Text object at 0x53a73d0>, <matplotlib.text.Text object at 0x53a7a50>, 
<matplotlib.text.Text object at 0x53aa110>, <matplotlib.text.Text object at 0x53aa790>]
>>> plt.show()

и результат: введите описание изображения здесь

и теперь, если вы проверите _xticklabels, их больше нет ''.

>>> [item.get_text() for item in axes.get_xticklabels()]
['0.0', 'change', '1.0', '1.5', '2.0']

Работает в версиях от 1.1.1rc1текущей версии 2.0.

CT Zhu
источник
Спасибо, это ответ, который я искал. Чистое решение ИМО; просто предоставьте set_xticklabelsсмешанный список строк и тиковых объектов.
Люк Дэвис
Имейте в виду, что если метки тиков установлены как целые, это изменит их на плавающие. Легко обходится, но стоит отметить.
Приближается к
Этот работал ( ax.get_xticks().tolist()). Решение с наибольшим количеством голосов не ( ax.get_xtickslabels()). Каким-то образом он не смог извлечь ярлыки до того, как plt.show()был извинен, хотя я использовал, fig.canvas.draw()как предлагалось.
CypherX
К вашему сведению, из современных документов matplotlib : «pylab устарела, и его использование настоятельно не рекомендуется из-за загрязнения пространства имен. Вместо этого используйте pyplot».
Натаниэль Джонс
17

Прошло много времени с тех пор, как был задан этот вопрос. На сегодняшний день ( matplotlib 2.2.2) и после некоторых чтений и испытаний, я думаю, что лучший / правильный способ заключается в следующем:

Matplotlib имеет модуль с именем , tickerкоторый «содержит классы для поддержки полностью настраиваемый клещом размещая и форматирования» . Чтобы изменить определенный тик из сюжета, у меня работает следующее:

import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np 

def update_ticks(x, pos):
    if x == 0:
        return 'Mean'
    elif pos == 6:
        return 'pos is 6'
    else:
        return x

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
ax.hist(data, bins=25, edgecolor='black')
ax.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
plt.show()

Гистограмма со случайными значениями из нормального распределения

Предостережение! xзначение тика и posего относительное положение по порядку на оси. Обратите внимание, что при индексации posпринимаются значения, начинающиеся с 1, а не 0как обычно.


В моем случае я пытался отформатировать y-axisгистограмму с процентными значениями. mtickerимеет другой класс, PercentFormatterкоторый может сделать это легко, без необходимости определять отдельную функцию, как раньше:

import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np 

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
weights = np.ones_like(data) / len(data)
ax.hist(data, bins=25, weights=weights, edgecolor='black')
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1.0, decimals=1))
plt.show()

Гистограмма со случайными значениями из нормального распределения

В данном случае xmaxэто значение данных, которое соответствует 100%. Проценты рассчитываются как x / xmax * 100, поэтому мы исправляем xmax=1.0. Кроме того, decimalsэто число десятичных знаков после точки.

iipr
источник
12

Класс axes имеет функцию set_yticklabels, которая позволяет вам устанавливать метки тиков , например:

#ax is the axes instance
group_labels = ['control', 'cold treatment',
             'hot treatment', 'another treatment',
             'the last one']

ax.set_xticklabels(group_labels)

Я все еще работаю над тем, почему ваш пример выше не сработал.

stanri
источник
3
Но я хочу изменить только один ярлык. Приведенный выше трюк требует, чтобы вы извлекли все метки тиков и установили желаемое новое значение. Но как я могу извлечь метки, когда label.get_text () ничего не возвращает?
repoman
11

Это работает:

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots(1,1)

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

ax1.set_xticks(x1)
ax1.set_xticklabels(squad, minor=False, rotation=45)

федералы

Soham
источник
7

Это также работает в matplotlib 3:

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

plt.xticks(x1, squad, rotation=45)
MichaelSB
источник
5

Если вы не работаете с figи axхотите изменить все метки (например, для нормализации), вы можете сделать это:

labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))
dopexxx
источник
1

Попробуй это :

  fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
  axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)
Аймен Альсаади
источник
-4

ты можешь сделать:

for k in ax.get_xmajorticklabels():
    if some-condition:
        k.set_color(any_colour_you_like)

draw()
Хати Манзур
источник
Может кто-нибудь объяснить, почему этот ответ так сильно опущен?
Хлынур Давид Хлинссон
@ HlynurDavíðHlynsson Я думаю, что это не имеет никакого отношения к вопросу. Ну, может быть, с некоторым редактированием ... Пожалуйста, отредактируйте его, если вы захотите связать это с вопросом. ;)
love.by.Iesus