Ändern Sie den Text der Häkchenbezeichnung

215

Ich möchte einige Änderungen an einigen ausgewählten Häkchen in einem Plot vornehmen.

Zum Beispiel, wenn ich:

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

Die Schriftgröße und die Ausrichtung des Häkchens werden geändert.

Wenn Sie jedoch Folgendes versuchen:

label.set_text('Foo')

Das Häkchen wird nicht geändert. Auch wenn ich das tue:

print label.get_text()

nichts wird gedruckt.

Hier ist noch etwas Seltsames. Als ich das versuchte:

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

Es werden nur leere Zeichenfolgen gedruckt, aber das Diagramm enthält Häkchen mit den Bezeichnungen "0.0", "0.5", "1.0", "1.5" und "2.0".

repoman
quelle
Können Sie das Grundstück angeben, von dem Sie das Etikett erhalten haben?
Claudio
Sie erhalten leere Etiketten, weil Sie die Leinwand noch nicht gezeichnet haben. Wenn Sie anrufen, draw()bevor Sie versuchen, die Etiketten zu drucken, erhalten Sie das, was Sie erwarten. Das Festlegen einzelner Tick-Labels ist leider etwas schwieriger (was passiert, ist, dass der Tick-Locator und der Formatierer nicht zurückgesetzt wurden und Dinge überschreiben, wenn Sie set_text). Ich werde gleich ein Beispiel hinzufügen, wenn mich jemand nicht schlägt. Im Moment muss ich allerdings den Bus nehmen.
Joe Kington
@ JoeKington: Großartig! Ich freue mich darauf, Ihren Fix zu sehen.
Repoman
@repoman - Nun, es scheint, ich habe zu früh eine Berührung gesprochen. Was ich mir vorgestellt habe, funktioniert für ältere Versionen von matplotlib, aber nicht für die neueste Version. Ich muss ein bisschen mehr graben. Davon abgesehen sollte dies nicht so kompliziert sein wie es ist ...
Joe Kington

Antworten:

298

Vorsichtsmaßnahme: Sofern die Ticklabels nicht bereits auf eine Zeichenfolge festgelegt sind (wie dies normalerweise bei einem Boxplot der Fall ist), funktioniert dies mit keiner neueren Version von matplotlib als 1.1.0. Wenn Sie vom aktuellen Github-Master aus arbeiten, funktioniert dies nicht. Ich bin mir noch nicht sicher, wo das Problem liegt ... Es kann eine unbeabsichtigte Änderung sein, oder es kann nicht sein ...

Normalerweise würden Sie etwas in diese Richtung tun:

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

Geben Sie hier die Bildbeschreibung ein

Um den Grund zu verstehen, warum Sie durch so viele Reifen springen müssen, müssen Sie etwas mehr darüber verstehen, wie matplotlib aufgebaut ist.

Matplotlib vermeidet absichtlich das "statische" Positionieren von Zecken usw., es sei denn, es wird ausdrücklich dazu aufgefordert. Die Annahme ist, dass Sie mit dem Plot interagieren möchten, sodass sich die Grenzen des Plots, der Ticks, der Ticklabels usw. dynamisch ändern.

Daher können Sie nicht einfach den Text eines bestimmten Häkchens festlegen. Standardmäßig wird es bei jedem Zeichnen des Diagramms durch den Locator und den Formatierer der Achse zurückgesetzt.

Wenn jedoch die Locators und Formatter gesetzt sind statisch zu sein ( FixedLocatorund FixedFormattersind), dann bleiben die Etiketten tick gleich.

Das ist was set_*ticklabelsoder ax.*axis.set_ticklabelstut.

Hoffentlich wird dadurch etwas klarer, warum das Ändern eines einzelnen Tick-Labels etwas kompliziert ist.

Oft möchten Sie nur eine bestimmte Position mit Anmerkungen versehen. In diesem Fall schauen Sie annotatestattdessen in.

Joe Kington
quelle
10
Dies scheint mit der aktuellen Version (1.20) nicht zu funktionieren!
Andrew Jaffe
1
Wenn die Ticklabels bereits auf eine Zeichenfolge wie in einem Boxplot festgelegt sind, funktioniert dies immer noch. Dies mag offensichtlich sein, aber da die erste Zeile der Antwort lautet, dass es nicht auf neueren matplotlib-Versionen funktioniert, können Benutzer es vollständig überspringen (ich habe es anfangs getan). Vielleicht kurz erwähnen.
Joelostblom
2
Ich denke, Sie können es auf plt.gca ()
Alexey
Was ist, wenn ich das Schriftgewicht von "Testen" haben möchte, boldwährend andere das Schriftgewicht von "Licht" verwenden? Gibt es eine Möglichkeit, dies zu tun?
Steven
1
Für diejenigen, die dies in einem Jupyter-Notizbuch verwenden, kann es von Vorteil sein, dass dies von fig.canvas.draw()entscheidender Bedeutung ist
wander95
95

Dies kann man auch mit Pylab und xticks machen

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
quelle
Dies ist eine einfache Lösung und funktioniert mit Pyplot 1.5.1. Dies sollte positiv bewertet werden.
Wortschmied
Obwohl die Frage dies nicht gestellt hat, weiß ich zu schätzen, dass Sie in diesem Beispiel die Position der Häkchen gleichzeitig mit dem Ändern ihrer Beschriftungen festlegen können.
Eclark
Aus modernen Matplotlib-Dokumenten : "Pylab ist veraltet und von seiner Verwendung wird aufgrund der Verschmutzung durch Namespaces dringend abgeraten. Verwenden Sie stattdessen Pyplot."
Nathaniel Jones
93

matplotlibWenn Sie in neueren Versionen von die Tick-Beschriftungen nicht mit einer Reihe von strWerten festlegen, sind sie ''standardmäßig (und wenn das Diagramm gezeichnet wird, sind die Beschriftungen einfach die Tick-Werte). Um dies zu erreichen, wäre Folgendes erforderlich, um die gewünschte Ausgabe zu erzielen:

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

und das Ergebnis: Geben Sie hier die Bildbeschreibung ein

und jetzt, wenn Sie das überprüfen _xticklabels, sind sie nicht mehr ein Haufen von ''.

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

Es funktioniert in den Versionen von 1.1.1rc1bis zur aktuellen Version 2.0.

CT Zhu
quelle
Danke, das ist die Antwort, nach der ich gesucht habe. Sauberste Lösung IMO; Geben Sie einfach set_xticklabelseine gemischte Liste mit Zeichenfolgen und Häkchen an.
Luke Davis
Beachten Sie, dass die Tick-Beschriftungen, wenn sie als Ints festgelegt sind, in Floats geändert werden. Leicht zu umgehen, aber erwähnenswert.
Annäherung
Dieser hat funktioniert ( ax.get_xticks().tolist()). Die am häufigsten gewählte Lösung war nicht ( ax.get_xtickslabels()). Irgendwie war es nicht möglich, die Etiketten zu extrahieren, bevor das ausgeschnitten plt.show()wurde, obwohl ich es fig.canvas.draw()wie vorgeschlagen verwendet habe.
CypherX
Zu Ihrer Information , aus modernen Matplotlib-Dokumenten : "Pylab ist veraltet und seine Verwendung wird aufgrund der Verschmutzung des Namespaces dringend empfohlen. Verwenden Sie stattdessen Pyplot."
Nathaniel Jones
17

Es ist schon eine Weile her, seit diese Frage gestellt wurde. Ab heute ( matplotlib 2.2.2) und nach einigen Lektüren und Versuchen denke ich, dass der beste / richtige Weg der folgende ist:

Matplotlib hat einen Modul mit dem Namen , tickerdass „enthält Klassen zur Unterstützung vollständig konfigurierbar tick Ortung und Formatierung“ . Um einen bestimmten Tick aus dem Plot zu ändern, funktioniert Folgendes für mich:

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

Histogramm mit Zufallswerten aus einer Normalverteilung

Vorbehalt! xist der Wert des Häkchens und posseine relative Position in der Reihenfolge in der Achse. Beachten Sie, dass posWerte beginnend mit 1und nicht 0wie üblich bei der Indizierung verwendet werden.


In meinem Fall habe ich versucht, das y-axiseines Histogramms mit Prozentwerten zu formatieren . mtickerhat eine andere Klasse namens PercentFormatter, die dies einfach tun kann, ohne wie zuvor eine separate Funktion definieren zu müssen:

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

Histogramm mit Zufallswerten aus einer Normalverteilung

In diesem Fall xmaxist der Datenwert 100%. Prozentsätze werden berechnet als x / xmax * 100, deshalb korrigieren wir xmax=1.0. Außerdem decimalswird die Anzahl der Dezimalstellen nach dem Punkt angegeben.

iipr
quelle
12

Die Achsenklasse hat eine Achsenklasse Funktion set_yticklabels , mit der Sie die Tick-Beschriftungen wie folgt festlegen können:

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

ax.set_xticklabels(group_labels)

Ich arbeite immer noch daran, warum Ihr Beispiel oben nicht funktioniert hat.

Stanri
quelle
3
Aber ich möchte nur ein einziges Etikett ändern. Der obige Trick erfordert, dass Sie alle Tick-Labels extrahieren und das gewünschte auf einen neuen Wert setzen. Aber wie kann ich die Tick-Labels extrahieren, wenn label.get_text () nichts zurückgibt?
Repoman
11

Das funktioniert:

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
quelle
7

Dies funktioniert auch in Matplotlib 3:

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

plt.xticks(x1, squad, rotation=45)
MichaelSB
quelle
5

Wenn Sie nicht mit figund arbeiten axund alle Beschriftungen ändern möchten (z. B. zur Normalisierung), können Sie dies tun:

labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))
dopexxx
quelle
1

Versuche dies :

  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
quelle
-4

du kannst tun:

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

draw()
Hachi Manzur
quelle
Kann jemand erklären, warum diese Antwort so stark abgelehnt wird?
Hlynur Davíð Hlynsson
@ HlynurDavíðHlynsson Ich denke, es hat nicht wirklich etwas mit der Frage zu tun. Nun, vielleicht mit etwas Bearbeitung ... Bitte bearbeiten Sie es, wenn Sie es mit der Frage in Verbindung bringen können. ;)
geliebt von Jesus