Zmodyfikuj tekst etykiety kleszcza

216

Chcę wprowadzić zmiany w kilku wybranych etykietach zaznaczenia na wykresie.

Na przykład, jeśli zrobię:

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

rozmiar czcionki i orientacja etykiety zaznaczenia zostały zmienione.

Jeśli jednak spróbujesz:

label.set_text('Foo')

etykieta wyboru nie jest modyfikowana. Również jeśli zrobię:

print label.get_text()

nic nie jest drukowane.

Oto trochę więcej dziwności. Kiedy spróbowałem:

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

Drukowane są tylko puste ciągi, ale wykres zawiera znaczniki oznaczone jako „0,0”, „0,5”, „1,0”, „1,5” i „2,0”.

repoman
źródło
Czy możesz podać fabułę użytą do uzyskania etykiety?
Claudio
Dostajesz puste etykiety, ponieważ nie narysowałeś jeszcze płótna. Jeśli zadzwonisz draw()przed próbą wydrukowania etykiet, otrzymasz to, czego oczekujesz. Ustawienie poszczególnych etykiet kleszczy jest niestety trudniejsze (dzieje się tak, że lokalizator i formatyzator kleszczy nie został zresetowany i nadpisuje rzeczy, gdy Ty set_text). Dodaję za chwilę przykład, jeśli ktoś mnie nie pobije. Jednak w tej chwili muszę złapać autobus.
Joe Kington
@JoeKington: Świetnie! Czekamy na Twoją poprawkę.
repoman
@repoman - Wygląda na to, że zbyt wcześnie rozmawiałem. To, co miałem na myśli, działa dla starszych wersji matplotlib, ale nie dla najnowszej wersji. Muszę trochę kopać. To powiedziawszy, nie powinno to być tak skomplikowane, jak to jest ...
Joe Kington

Odpowiedzi:

298

Zastrzeżenie: Chyba, że ​​znaczniki są już ustawione na ciąg znaków (jak to zwykle ma miejsce np. W przypadku wykresu pudełkowego), nie zadziała to z żadną wersją Matplotlib nowszą niż 1.1.0 . Jeśli pracujesz z obecnego mistrza github, to nie zadziała. Nie jestem jeszcze pewien, na czym polega problem ... Może to być niezamierzona zmiana lub może nie być ...

Zwykle zrobiłbyś coś według następujących zasad:

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

wprowadź opis zdjęcia tutaj

Aby zrozumieć powód, dla którego musisz skakać przez tak wiele obręczy, musisz dowiedzieć się nieco więcej o strukturze matplotlib.

Matplotlib celowo unika wykonywania „statycznego” pozycjonowania kleszczy itp., Chyba że jest to wyraźnie nakazane. Założeniem jest, że będziesz chciał wchodzić w interakcje z fabułą, więc granice fabuły, tyknięć, naklejek itp. Będą się dynamicznie zmieniać.

Dlatego nie można po prostu ustawić tekstu danej etykiety kleszcza. Domyślnie jest on ponownie ustawiany przez Lokalizator osi i Formatyzator za każdym razem, gdy rysowany jest wykres.

Jeśli jednak Lokalizatory i Formatery są ustawione na statyczne ( FixedLocatori FixedFormatterodpowiednio), wówczas etykiety wyboru pozostają takie same.

To jest co set_*ticklabelslub ax.*axis.set_ticklabelsrobi.

Mamy nadzieję, że to nieco wyjaśnia, dlaczego zmiana indywidualnej etykiety kleszczy jest nieco skomplikowana.

Często to, co naprawdę chcesz zrobić, to po prostu przypisać określoną pozycję. W takim przypadku spójrz annotatezamiast tego.

Joe Kington
źródło
10
to nie wydaje się działać z bieżącą wersją (1.20)!
Andrew Jaffe
1
Jeśli znaczniki są już ustawione na ciąg znaków, jak np. Na wykresie pudełkowym, nadal działa. Może to być oczywiste, ale ponieważ pierwsza linia odpowiedzi brzmi: nie działa ona na nowszych wersjach matplotlib, użytkownicy mogą ją całkowicie pominąć (początkowo tak zrobiłem). Może krótko o tym wspomnę.
joelostblom
2
myślę, że możesz to skondensować do plt.gca (). set_xticklabels (etykiety)
alexey,
co jeśli chcę, aby czcionka „testowania” była, boldpodczas gdy inni używają czcionki „light”. Czy jest na to sposób?
Steven
1
dla tych, którzy używają tego w notatniku jupyter, warto zauważyć, że fig.canvas.draw()jest to kluczowe
wander95
96

Można to również zrobić za pomocą pylab i 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
źródło
Jest to proste rozwiązanie i działa z pyplot 1.5.1. To powinno być ocenione pozytywnie.
wordmith
Chociaż pytanie nie wymagało tego, doceniam, że ten przykład pozwala ci ustawić lokalizację kleszczy jednocześnie z modyfikacją ich etykiet.
eklark
Od nowoczesnego dokumentów matplotlib : „pylab jest przestarzały, a jego użycie jest mocno odradzane z powodu zanieczyszczenia przestrzeni nazw. Zamiast tego użyj pyplot”.
Nathaniel Jones
93

W nowszych wersjach matplotlib, jeśli nie ustawisz etykiet kleszczy za pomocą szeregu strwartości, są one ''domyślnie (a gdy rysowany jest wykres, etykiety są po prostu wartościami kleszczy). Wiedząc o tym, uzyskanie pożądanej wydajności wymagałoby czegoś takiego:

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

a wynik: wprowadź opis zdjęcia tutaj

a teraz, jeśli sprawdzisz _xticklabels, nie są już grupą ''.

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

Działa w wersjach od 1.1.1rc1do bieżącej wersji 2.0.

CT Zhu
źródło
Dzięki, to była odpowiedź, której szukałem. Najczystsze rozwiązanie IMO; po prostu podaj set_xticklabelsmieszaną listę ciągów znaków i zaznacz obiekty.
Luke Davis,
Należy pamiętać, że jeśli etykiety znaczników są ustawione jako ints, spowoduje to zmianę ich na zmiennoprzecinkowe. Łatwo pracował, ale warto zauważyć.
ApproachingDarknessFish
Ten działał ( ax.get_xticks().tolist()). Najczęściej głosowane rozwiązanie nie ( ax.get_xtickslabels()). Jakoś nie było w stanie wyodrębnić etykiet przed plt.show()ekscytacją, chociaż użyłem fig.canvas.draw()zgodnie z sugestią.
CypherX,
FYI, z nowoczesnych dokumentów matplotlib : „pylab jest przestarzały, a jego użycie jest zdecydowanie odradzane z powodu zanieczyszczenia przestrzeni nazw. Zamiast tego użyj pyplot”.
Nathaniel Jones
17

Minęło trochę czasu, odkąd zadano to pytanie. Na dzień dzisiejszy ( matplotlib 2.2.2) i po kilku lekturach i próbach uważam, że najlepszym / właściwym sposobem jest:

Matplotlib ma moduł o nazwie ticker, która „zawiera klasy do wsparcia całkowicie konfigurowalnym lokalizowania kleszcza i formatowania” . Aby zmodyfikować konkretny tik z wykresu, dla mnie działa:

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

Histogram z losowymi wartościami z rozkładu normalnego

Zastrzeżenie! xjest wartością tik i posjest jego względną pozycją w kolejności w osi. Zauważ, że poswartości zaczynają się od 1, a nie 0jak zwykle podczas indeksowania.


W moim przypadku próbowałem sformatować y-axishistogram za pomocą wartości procentowych. mtickerma inną klasę o nazwie, PercentFormatterktóra może to zrobić łatwo bez potrzeby definiowania oddzielnej funkcji jak poprzednio:

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

Histogram z losowymi wartościami z rozkładu normalnego

W tym przypadku xmaxjest to wartość danych odpowiadająca 100%. Wartości procentowe są obliczane jako x / xmax * 100, dlatego naprawiamy xmax=1.0. Ponadto decimalsjest liczbą miejsc dziesiętnych do umieszczenia po kropce.

iipr
źródło
12

Klasa axes ma funkcję set_yticklabels, która pozwala ustawić etykiety znaczników, w następujący sposób:

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

ax.set_xticklabels(group_labels)

Nadal pracuję nad tym, dlaczego powyższy przykład nie zadziałał.

stanri
źródło
3
Ale chcę zmienić tylko jedną etykietę. Powyższa sztuczka wymaga wyodrębnienia wszystkich etykiet kleszczy i ustawienia żądanej na nową wartość. Ale jak mogę wyodrębnić etykiety zaznaczenia, gdy label.get_text () nic nie zwraca?
repoman
11

To działa:

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)

FEDS

Soham
źródło
7

Działa to również w Matplotlib 3:

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

plt.xticks(x1, squad, rotation=45)
MichaelSB
źródło
5

Jeśli nie współpracujesz figi axchcesz zmodyfikować wszystkie etykiety (np. W celu normalizacji), możesz to zrobić:

labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))
dopexxx
źródło
1

Spróbuj tego :

  fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
  axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)
Aymen Alsaadi
źródło
-4

możesz to zrobić:

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

draw()
Hachi Manzur
źródło
Czy ktoś może wyjaśnić, dlaczego ta odpowiedź jest tak mocno oceniana?
Hlynur Davíð Hlynsson
@ HlynurDavíðHlynsson Myślę, że tak naprawdę nie ma to nic wspólnego z tym pytaniem. Cóż, może z pewną edycją ... Edytuj to, jeśli możesz odnieść się do pytania. ;)
loved.by.Jesus