Ändern der „Tick-Frequenz“ auf der x- oder y-Achse in matplotlib?

477

Ich versuche zu korrigieren, wie Python meine Daten zeichnet.

Sagen

x = [0,5,9,10,15]

und

y = [0,1,2,3,4]

Dann würde ich tun:

matplotlib.pyplot.plot(x,y)
matplotlib.pyplot.show()

und die Ticks der x-Achse werden in Intervallen von 5 aufgezeichnet. Gibt es eine Möglichkeit, Intervalle von 1 anzuzeigen?

Dax Feliz
quelle
6
Obwohl Zecken hier das richtige Wort sind, führt das Ändern der Zecken in die Schrittgröße definitiv mehr Neulinge zu dieser Frage.
Sibbs Gambling
9
Eng verwandte Frage: stackoverflow.com/questions/6682784/… und eine großartige Lösung:pyplot.locator_params(nbins=4)
Dr. Jan-Philip Gehrcke
nbins scheint in matplotlib2.x leider veraltet gewesen zu sein
jeremy_rutman

Antworten:

583

Sie können explizit festlegen, wo Sie Markierungen ankreuzen möchten plt.xticks:

plt.xticks(np.arange(min(x), max(x)+1, 1.0))

Zum Beispiel,

import numpy as np
import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()

( np.arangewurde für alle rangeFälle anstelle von Pythons Funktion verwendet min(x)und max(x)ist Floats anstelle von Ints.)


Die plt.plot(oder ax.plot) Funktion legt automatisch Standardeinstellungen xund yGrenzwerte fest. Wenn Sie diese Grenzwerte beibehalten und nur die Schrittweite der Häkchen ändern möchten, können Sie ermitteln ax.get_xlim(), welche Grenzwerte Matplotlib bereits festgelegt hat.

start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, stepsize))

Der Standard-Tick-Formatierer sollte gute Arbeit leisten und die Tick-Werte auf eine sinnvolle Anzahl signifikanter Stellen runden. Wenn Sie jedoch mehr Kontrolle über das Format haben möchten, können Sie Ihren eigenen Formatierer definieren. Zum Beispiel,

ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))

Hier ist ein lauffähiges Beispiel:

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

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, 0.712123))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
plt.show()
unutbu
quelle
72
Gibt es keine Möglichkeit, es dazu zu bringen, seine eigenen Grenzen zu bestimmen, sondern nur die Schrittgröße zu ändern? Diese Methode ist nicht sehr gut, wenn die min so etwas wie 3523.232512 ist!
Korone
3
@Corone, es ist schon eine Weile her, seit Sie gefragt haben, aber ich habe unten eine Antwort gepostet, die eine einfache Kontrolle der Schrittgröße ermöglicht, während die automatische Grenzwertbestimmung weiterhin verwendet wird.
Thomas
3
Beachten Sie, dass das +1In plt.xticks(np.arange(min(x), max(x)+1, 1.0))erforderlich ist, um das letzte Häkchen anzuzeigen.
Alex Willison
1
Ja, np.arange(start, stop)generiert Werte im halboffenen Intervall [start, stop), einschließlich, startaber ausschließlich stop. Also habe ich immer dafür max(x)+1gesorgt, dass max(x)das enthalten ist.
Unutbu
4
Gibt es ein Äquivalent für datetime, z plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1). es scheint nur das Jahr zu
zeichnen
207

Ein anderer Ansatz besteht darin, den Achsen-Locator einzustellen:

import matplotlib.ticker as plticker

loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)

Abhängig von Ihren Anforderungen gibt es verschiedene Arten von Ortungsgeräten.

Hier ist ein vollständiges Beispiel:

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)
plt.show()
Robochat
quelle
7
Dies funktioniert nicht wie erwartet. Insbesondere bei der Verwendung von Datumsangaben werden nicht die entsprechenden Datumsangaben verwendet.
Chris Fonnesbeck
35
Wenn Sie Datumsangaben verwenden, sollten Sie die Methoden im Modul matplotlib.dates verwenden. Zum Beispielmatplotlib.dates.AutoDateLocator()
Robochat
3
Es funktionierte wie erwartet für mich, mit Daten. Diese Lösung ist viel einfacher als die akzeptierte.
Pablo Suau
Was bedeutet base=1.0eigentlich?
Javadba
base = 1.0 bedeutet, dass für jede ganze Zahl ein Locator vorhanden ist. In der Dokumentation heißt es, dass MultipleLocator "ein Häkchen für jedes ganzzahlige Vielfache einer Basis innerhalb des Ansichtsintervalls setzt." Wenn also base = 2 ist, gibt es ein Häkchen für gerade Zahlen und ich denke, Sie könnten event base = 2.5 setzen.
Robochat
124

Ich mag diese Lösung (aus dem Matplotlib Plotting Cookbook ):

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]

tick_spacing = 1

fig, ax = plt.subplots(1,1)
ax.plot(x,y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()

Diese Lösung gibt Ihnen eine explizite Kontrolle des Tick-Abstands über die angegebene Nummer ticker.MultipleLocater(), ermöglicht die automatische Grenzwertbestimmung und ist später leicht abzulesen.

jthomas
quelle
3
Eine Möglichkeit, dies zu tun, ohne die Ticks explizit zu berechnen!
Zelphir Kaltstahl
4
Dies ist die gleiche Antwort wie diese . Es ist nicht sinnvoll, zwei Jahre später eine identische Antwort hinzuzufügen.
ImportanceOfBeingErnest
6
Guter Fang. Ich habe sie nicht als gleich erkannt, als ich die Antwort gepostet habe. Trotzdem denke ich, dass diese Präsentation etwas einfacher zu verstehen ist.
Thomas
Die Buchreferenz in dieser Antwort bietet auch eine hilfreiche Quelle für weitere Informationen.
Steven C. Howell
1
Dies ist die gleiche Antwort wie die von Robochat, die drei Jahre zuvor kam.
MERose
90

Wenn sich jemand für einen allgemeinen Einzeiler interessiert, holen Sie sich einfach die aktuellen Ticks und setzen Sie damit die neuen Ticks, indem Sie jeden zweiten Tick abtasten.

ax.set_xticks(ax.get_xticks()[::2])
Glopes
quelle
3
Dies ist die einzige verallgemeinerbare Antwort für verschiedene Tick-Typen (str, float, datetime)
Ryszard Cetnarski
2
Entfernen Sie nicht ganzzahlige Ticks: ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
user2839288
Viele detaillierte Lösungen oben, aber ich stimme zu, dass dies die prägnanteste ist. Sie können sogar die Länge von ax.get_xticks () extrahieren und die Schnittfrequenz durch diese Länge geteilt durch die Anzahl der erforderlichen Ticks festlegen.
Iain D
Ich denke, das ist die beste Antwort. Die meisten anderen Antworten sind zu kompliziert und schwer anzuwenden / zu verallgemeinern. Vielen Dank!
Seankala
2
Es kann nur die Anzahl der Stöcke reduzieren, während in der Frage (und meinem Ziel, wie ich es gefunden habe) es war, es zu erhöhen.
Alexei Martianov
36

Dies ist ein bisschen hackig, aber bei weitem das sauberste / am einfachsten zu verstehende Beispiel, das ich dafür gefunden habe. Es ist von einer Antwort auf SO hier:

Der sauberste Weg, jedes n-te Häkchen in der Matplotlib-Farbleiste zu verstecken?

for label in ax.get_xticklabels()[::2]:
    label.set_visible(False)

Anschließend können Sie die Beschriftungen durchlaufen und sie je nach gewünschter Dichte als sichtbar oder nicht sichtbar festlegen.

Bearbeiten: Beachten Sie, dass matplotlib manchmal Beschriftungen == setzt '', sodass es möglicherweise so aussieht, als ob eine Beschriftung nicht vorhanden ist, obwohl sie tatsächlich nichts anzeigt. Um sicherzustellen, dass Sie die tatsächlich sichtbaren Beschriftungen durchlaufen, können Sie Folgendes versuchen:

visible_labels = [lab for lab in ax.get_xticklabels() if lab.get_visible() is True and lab.get_text() != '']
plt.setp(visible_labels[::2], visible=False)
Choldgraf
quelle
3
Dies ist die einfachste und allgemeinste Lösung. Eine winzige Anpassung: Normalerweise müssen ax.get_xticklabels()[1::2]die Etiketten ausgeblendet werden.
Jolvi
Dies funktioniert nicht mit matplotlib.finance.candlestick2
BCR
@BCR Es kann sein, dass einige der xticklabels nur so eingestellt sind, ''dass Sie beim Durchlaufen leere Xticklabels unsichtbar machen (was keine Auswirkungen auf die Visualisierung hätte, aber möglicherweise bedeutet, dass Sie nicht ziehen die richtigen Etiketten). Sie könnten versuchen: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
Choldgraf
15

Dies ist ein altes Thema, aber ich stolpere hin und wieder darüber und habe diese Funktion gemacht. Es ist sehr praktisch:

import matplotlib.pyplot as pp
import numpy as np

def resadjust(ax, xres=None, yres=None):
    """
    Send in an axis and I fix the resolution as desired.
    """

    if xres:
        start, stop = ax.get_xlim()
        ticks = np.arange(start, stop + xres, xres)
        ax.set_xticks(ticks)
    if yres:
        start, stop = ax.get_ylim()
        ticks = np.arange(start, stop + yres, yres)
        ax.set_yticks(ticks)

Eine Einschränkung bei der Steuerung solcher Zecken besteht darin, dass man die interaktive automatische Aktualisierung der maximalen Skalierung nach einer hinzugefügten Zeile nicht mehr genießt. Dann mach

gca().set_ylim(top=new_top) # for example

und führen Sie die Resadjust-Funktion erneut aus.

Tompa
quelle
11

Ich habe eine unelegante Lösung entwickelt. Bedenken Sie, dass wir die X-Achse und auch eine Liste von Beschriftungen für jeden Punkt in X haben.

Beispiel:
import matplotlib.pyplot as plt

x = [0,1,2,3,4,5]
y = [10,20,15,18,7,19]
xlabels = ['jan','feb','mar','apr','may','jun']
Angenommen, ich möchte Zeckenbezeichnungen nur für 'feb' und 'jun' anzeigen.
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Gut, jetzt haben wir eine gefälschte Liste von Etiketten. Zuerst haben wir die Originalversion gezeichnet.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Nun die modifizierte Version.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()
Deninhos
quelle
6

Wenn Sie nur den Abstand auf einen einfachen Einzeiler mit minimaler Boilerplate einstellen möchten:

plt.gca().xaxis.set_major_locator(plt.MultipleLocator(1))

funktioniert auch leicht bei kleinen Zecken:

plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))

ein bisschen mundvoll, aber ziemlich kompakt

Gary Steele
quelle
2
xmarks=[i for i in range(1,length+1,1)]

plt.xticks(xmarks)

Das hat bei mir funktioniert

Wenn Sie Ticks zwischen [1,5] (einschließlich 1 und 5) wünschen, ersetzen Sie diese

length = 5
Piyush Gupta
quelle
1
Zu Ihrer Information, Sie könnten einfach schreiben xmarks = range(1, length+1, 1). ziemlich sicher, dass das Listenverständnis überflüssig ist.
Neal
2

Reine Python-Implementierung

Im Folgenden finden Sie eine reine Python-Implementierung der gewünschten Funktionalität, die alle numerischen Reihen (int oder float) mit positiven, negativen oder gemischten Werten verarbeitet und es dem Benutzer ermöglicht, die gewünschte Schrittgröße anzugeben:

import math

def computeTicks (x, step = 5):
    """
    Computes domain with given step encompassing series x
    @ params
    x    - Required - A list-like object of integers or floats
    step - Optional - Tick frequency
    """
    xMax, xMin = math.ceil(max(x)), math.floor(min(x))
    dMax, dMin = xMax + abs((xMax % step) - step) + (step if (xMax % step != 0) else 0), xMin - abs((xMin % step))
    return range(dMin, dMax, step)

Beispielausgabe

# Negative to Positive
series = [-2, 18, 24, 29, 43]
print(list(computeTicks(series)))

[-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

# Negative to 0
series = [-30, -14, -10, -9, -3, 0]
print(list(computeTicks(series)))

[-30, -25, -20, -15, -10, -5, 0]

# 0 to Positive
series = [19, 23, 24, 27]
print(list(computeTicks(series)))

[15, 20, 25, 30]

# Floats
series = [1.8, 12.0, 21.2]
print(list(computeTicks(series)))

[0, 5, 10, 15, 20, 25]

# Step – 100
series = [118.3, 293.2, 768.1]
print(list(computeTicks(series, step = 100)))

[100, 200, 300, 400, 500, 600, 700, 800]

Beispielnutzung

import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(computeTicks(x))
plt.show()

Darstellung der Probennutzung

Beachten Sie, dass die x-Achse ganzzahlige Werte hat, die alle gleichmäßig um 5 voneinander beabstandet sind, während die y-Achse ein anderes Intervall hat (das matplotlibStandardverhalten, da die Häkchen nicht angegeben wurden).

Greenstick
quelle