Cambiare la "frequenza di tick" sull'asse x o y in matplotlib?


477

Sto cercando di risolvere il modo in cui Python traccia i miei dati.

Dire

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

e

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

Quindi farei:

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

e i segni di spunta dell'asse x sono tracciati a intervalli di 5. C'è un modo per farlo mostrare a intervalli di 1?


6
Sebbene le zecche siano la parola appropriata qui, cambiare le zecche nella dimensione del passo guiderà sicuramente più neofiti a questa domanda.
Sibbs Gioco d'azzardo

9
Domanda strettamente correlata: stackoverflow.com/questions/6682784/… e un'ottima soluzione:pyplot.locator_params(nbins=4)
Dr. Jan-Philip Gehrcke,

nbins sembra essere stato deprecato in matplotlib2.x, sfortunatamente
jeremy_rutman

Risposte:


584

È possibile impostare esplicitamente dove si desidera contrassegnare i segni con plt.xticks:

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

Per esempio,

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.arangestato usato piuttosto che la rangefunzione di Python per ogni evenienza min(x)e max(x)sono float anziché ints.)


La funzione plt.plot(o ax.plot) imposterà automaticamente valori predefiniti xe ylimiti. Se si desidera mantenere tali limiti e modificare semplicemente la dimensione dei segni di spunta, è possibile utilizzare ax.get_xlim()per scoprire quali limiti sono già stati impostati da Matplotlib.

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

Il formatter di tick predefinito dovrebbe fare un lavoro decente arrotondando i valori di tick a un numero ragionevole di cifre significative. Tuttavia, se desideri avere un maggiore controllo sul formato, puoi definire il tuo formattatore. Per esempio,

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

Ecco un esempio eseguibile:

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

72
Non c'è modo di convincerlo a decidere ancora i propri limiti, ma basta cambiare la dimensione del passo? Questo metodo non è molto valido se il valore minimo è 3523.232512!
Korone,

3
@Corone, è da un po 'che non lo chiedi, ma di seguito ho pubblicato una risposta che consente un facile controllo della dimensione del passo mentre si utilizza ancora la determinazione automatica dei limiti.
jthomas,

3
Si noti che +1in plt.xticks(np.arange(min(x), max(x)+1, 1.0))è necessario per mostrare l'ultimo segno di spunta.
Alex Willison,

1
Sì, np.arange(start, stop)genera valori nella semiaperta intervallo [start, stop), incluso startma esclusi stop. Quindi mi max(x)+1assicuravo che max(x)fosse incluso.
unutbu,

4
esiste un equivalente per datetime ad es plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)? sembra tracciare solo l'anno
WBM

207

Un altro approccio è quello di impostare il localizzatore degli assi:

import matplotlib.ticker as plticker

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

Esistono diversi tipi di localizzatore in base alle tue esigenze.

Ecco un esempio completo:

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

7
Questo non funziona come previsto. In particolare, quando si utilizzano le date, non utilizza le date appropriate.
Chris Fonnesbeck,

35
Quando si utilizzano le date, è necessario utilizzare i metodi nel modulo matplotlib.dates. Ad esempiomatplotlib.dates.AutoDateLocator()
robochat il

3
Ha funzionato come previsto per me, con le date. Questa soluzione è molto più semplice di quella accettata.
Pablo Suau,

Cosa significa base=1.0effettivamente / fare?
Javavba,

base = 1.0 significa che ci sarà un localizzatore per ogni numero intero. La documentazione afferma che MultipleLocator "Imposta un segno di spunta su ciascun multiplo intero di una base nell'intervallo di visualizzazione.". Quindi se base = 2 allora ci sarà un segno di spunta per i numeri pari e penso che potresti mettere put = 2.5.
robochat,

124

Mi piace questa soluzione (dal 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()

Questa soluzione offre un controllo esplicito della spaziatura dei tick tramite il numero indicato ticker.MultipleLocater(), consente la determinazione automatica dei limiti ed è facile da leggere in seguito.


3
Un modo per farlo senza calcolare esplicitamente le zecche!
Zelphir Kaltstahl,

4
Questa è la stessa risposta di questa . Non ha senso aggiungere una risposta identica due anni dopo.
ImportanceOfBeingErnest il

6
Buona pesca. Non le ho riconosciute uguali quando ho pubblicato la risposta. Tuttavia, penso che questa presentazione sia un po 'più facile da capire.
jthomas,

Il riferimento del libro in questa risposta fornisce anche una fonte utile per ulteriori informazioni.
Steven C. Howell,

1
Questa è la stessa risposta di quella del robochat, che è arrivata tre anni prima.
MERose

90

Nel caso in cui qualcuno sia interessato a un one-liner generale, è sufficiente ottenere i tick correnti e usarlo per impostare i nuovi tick campionando ogni altro tick.

ax.set_xticks(ax.get_xticks()[::2])

3
Questa è l'unica risposta generalizzabile per diversi tipi di tick (str, float, datetime)
Ryszard Cetnarski,

2
Rimuovere i ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
segni di spunta

Molte soluzioni dettagliate sopra ma concordo sul fatto che questa è la più concisa. È anche possibile estrarre la lunghezza di ax.get_xticks () e impostare la frequenza di taglio per questa lunghezza divisa per il numero di tick richiesti.
Iain D,

Penso che questa sia la risposta migliore. Molte altre risposte sono troppo complicate e difficili da applicare / generalizzare. Grazie!
Seankala,

2
Può solo ridurre il numero di stick, mentre nella domanda (e il mio obiettivo come l'ho trovato) era di aumentarlo.
Alexei Martianov,

36

Questo è un po 'confuso, ma di gran lunga l'esempio più pulito / più facile da capire che ho trovato per fare questo. Viene da una risposta su SO qui:

Il modo più pulito per nascondere ogni ennesima etichetta di spunta nella barra dei colori di matplotlib?

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

Quindi è possibile scorrere le etichette impostandole su visibile o meno a seconda della densità desiderata.

modifica: nota che a volte matplotlib imposta etichette == '', quindi potrebbe sembrare che un'etichetta non sia presente, quando in realtà lo è e non mostra nulla. Per assicurarti di passare in rassegna le etichette visibili effettive, puoi provare:

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)

3
Questa è la soluzione più semplice e generica. Una piccola regolazione: di solito ax.get_xticklabels()[1::2]sono le etichette da nascondere.
jolvi,

Questo non funziona con matplotlib.finance.candlestick2
BCR

@BCR potrebbe essere che alcuni degli xticklabel siano impostati in ''modo tale che quando li attraversi, stai rendendo xticklabels vuoti invisibili (il che non avrebbe alcun effetto sulla visualizzazione, ma potrebbe significare che non stai tirando le etichette corrette). Potresti provare: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf,

15

Questo è un vecchio argomento, ma mi imbatto in questo ogni tanto e ho fatto questa funzione. È molto conveniente:

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)

Un avvertimento per controllare le zecche in questo modo è che non si gode più l'aggiornamento automagico interattivo della scala massima dopo una riga aggiunta. Quindi fa

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

ed eseguire di nuovo la funzione resadjust.


11

Ho sviluppato una soluzione non elegante. Considera che abbiamo l'asse X e anche un elenco di etichette per ogni punto in X.

Esempio:
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']
Diciamo che voglio mostrare le etichette delle zecche solo per "feb" e "jun"
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Bene, ora abbiamo un falso elenco di etichette. Innanzitutto, abbiamo tracciato la versione originale.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Ora, la versione modificata.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

6

se vuoi solo impostare la spaziatura una semplice fodera con una piastra di cottura minima:

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

funziona anche facilmente per le zecche minori:

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

un po 'pieno, ma piuttosto compatto


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

plt.xticks(xmarks)

Questo ha funzionato per me

se si desidera un segno di spunta tra [1,5] (compreso tra 1 e 5), sostituire

length = 5

1
a proposito, potresti semplicemente scrivere xmarks = range(1, length+1, 1). abbastanza sicuro che la comprensione dell'elenco sia ridondante.
Neal,

2

Implementazione Pure Python

Di seguito è una pura implementazione in pitone della funzionalità desiderata che gestisce qualsiasi serie numerica (int o float) con valori positivi, negativi o misti e consente all'utente di specificare la dimensione del passo desiderata:

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)

Uscita campione

# 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]

Esempio di utilizzo

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

Grafico dell'utilizzo del campione

Notare che l'asse x ha valori interi tutti equamente distanziati di 5, mentre l'asse y ha un intervallo diverso (il matplotlibcomportamento predefinito, perché i segni di spunta non sono stati specificati).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.