Zmieniasz „częstotliwość tyknięcia” na osi x lub y w Matplotlib?


477

Próbuję naprawić sposób, w jaki Python drukuje moje dane.

Mówić

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

i

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

Potem zrobiłbym:

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

a tyknięcia na osi x są wykreślane w odstępach 5. Czy istnieje sposób, aby pokazywał odstępy 1?


6
Chociaż tiki są tutaj odpowiednim słowem, zmiana tików na rozmiar kroku z pewnością poprowadzi nowych początkujących do tego pytania.
Sibbs Gambling

9
Ściśle powiązane pytanie: stackoverflow.com/questions/6682784/... i świetne rozwiązanie:pyplot.locator_params(nbins=4)
Dr Jan-Philip Gehrcke

nbins wydaje się być przestarzałe w matplotlib2.x, niestety
jeremy_rutman

Odpowiedzi:


583

Możesz jawnie ustawić miejsce, w którym chcesz zaznaczyć znaczniki plt.xticks:

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

Na przykład,

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.arangezostał użyty zamiast rangefunkcji Pythona na wszelki wypadek min(x)i max(x)są zmiennoprzecinkowe zamiast ints.)


Funkcja plt.plot(lub ax.plot) automatycznie ustawi domyślne xi ylimity. Jeśli chcesz zachować te limity i po prostu zmienić rozmiar znaczników, możesz użyć, ax.get_xlim()aby dowiedzieć się, jakie limity Matplotlib już ustawił.

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

Domyślny formatyzator tików powinien wykonać przyzwoitą robotę zaokrąglając wartości tików do rozsądnej liczby cyfr znaczących. Jeśli jednak chcesz mieć większą kontrolę nad formatem, możesz zdefiniować własny formatyzator. Na przykład,

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

Oto możliwy do uruchomienia przykład:

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
Czy nie ma sposobu, aby nadal decydować o własnych limitach, ale po prostu zmienić rozmiar kroku? Ta metoda nie jest zbyt dobra, jeśli min ma wartość 3523.232512!
Korone

3
@Coreone, minęło trochę czasu, odkąd zapytałeś, ale zamieściłem poniżej odpowiedź, która pozwala na łatwą kontrolę wielkości kroku, nadal korzystając z automatycznego określania granic.
jthomas

3
Pamiętaj, że znak +1in plt.xticks(np.arange(min(x), max(x)+1, 1.0))jest wymagany, aby pokazać ostatni znacznik wyboru.
Alex Willison

1
Tak, np.arange(start, stop)generuje wartości w przedziale półotwartym[start, stop) , w tym, startale wykluczając stop. Więc kiedyś max(x)+1upewniałem się, że max(x)to jest uwzględnione.
unutbu

4
czy istnieje odpowiednik datetime np. plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)? wydaje się, że rysuje tylko rok
WBM

207

Innym podejściem jest ustawienie lokalizatora osi:

import matplotlib.ticker as plticker

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

Istnieje kilka różnych rodzajów lokalizatora w zależności od potrzeb.

Oto pełny przykład:

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
To nie działa zgodnie z oczekiwaniami. W szczególności podczas korzystania z dat nie używa odpowiednich dat.
Chris Fonnesbeck

35
Korzystając z dat, powinieneś użyć metod z modułu matplotlib.dates. Na przykładmatplotlib.dates.AutoDateLocator()
robochat

3
Działa zgodnie z oczekiwaniami, z datami. To rozwiązanie jest znacznie łatwiejsze niż przyjęte.
Pablo Suau

Co tak base=1.0naprawdę oznacza / robi?
javadba

base = 1.0 oznacza, że ​​dla każdej liczby całkowitej znajdzie się lokalizator. Dokumentacja mówi, że MultipleLocator „Ustaw zaznaczenie na każdej liczbie całkowitej wielokrotności podstawy w interwale wyświetlania”. Więc jeśli base = 2, to będzie znacznik dla liczb parzystych i myślę, że możesz umieścić event base = 2.5.
robochat

124

Podoba mi się to rozwiązanie (z 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()

To rozwiązanie daje ci wyraźną kontrolę odstępów między tyknięciami za pomocą podanej liczby ticker.MultipleLocater(), pozwala na automatyczne określenie limitu i jest łatwe do odczytania później.


3
Sposób na zrobienie tego bez jawnego obliczania tyknięć!
Zelphir Kaltstahl

4
To jest ta sama odpowiedź, co ta . Dodanie identycznej odpowiedzi dwa lata później nie ma sensu.
ImportanceOfBeingErnest

6
Dobry chwyt Nie rozpoznałem ich jako takich samych, kiedy opublikowałem odpowiedź. Myślę jednak, że ta prezentacja jest nieco łatwiejsza do zrozumienia.
jthomas

Odwołanie do książki w tej odpowiedzi stanowi również pomocne źródło dodatkowych informacji.
Steven C. Howell,

1
To ta sama odpowiedź, co robochata, który pojawił się trzy lata wcześniej.
MERose

90

W przypadku, gdy ktoś jest zainteresowany ogólną linią pojedynczą, po prostu pobierz bieżące tiki i użyj go do ustawienia nowych tików, próbkując co drugi tik.

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

3
To jedyna możliwa do uogólnienia odpowiedź na różne typy tików (str, float, datetime)
Ryszard Cetnarski,

2
Usuń znaczniki nie będące liczbami całkowitymi: ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
user2839288

Wiele szczegółowych rozwiązań powyżej, ale zgadzam się, że jest to najbardziej zwięzłe. Możesz nawet wyodrębnić długość ax.get_xticks () i ustawić częstotliwość krojenia przez tę długość podzieloną przez liczbę wymaganych tyknięć.
Iain D

Myślę, że to najlepsza odpowiedź. Większość innych odpowiedzi jest zbyt skomplikowana i trudna do zastosowania / uogólnienia. Dziękuję Ci!
Seankala

2
Może jedynie zmniejszyć liczbę drążków, podczas gdy w pytaniu (i moim celem jak to znalazłem) było zwiększenie.
Aleksiej Martianow

36

Jest to nieco zuchwałe, ale zdecydowanie najczystszy / najłatwiejszy do zrozumienia przykład, jaki to zrobiłem. Oto odpowiedź na SO tutaj:

Najczystszy sposób na ukrycie każdej n-tej etykiety kleszczowej w pasku kolorów Matplotlib?

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

Następnie możesz zapętlić etykiety, ustawiając je na widoczne lub nie, w zależności od żądanej gęstości.

edit: zauważ, że czasami matplotlib ustawia etykiety == '', więc może wyglądać na to, że etykieta nie jest obecna, podczas gdy w rzeczywistości jest i po prostu nic nie wyświetla. Aby mieć pewność, że przeglądasz rzeczywiste widoczne etykiety, możesz spróbować:

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
To jest najprostsze i ogólne rozwiązanie. Drobna korekta: zazwyczaj ax.get_xticklabels()[1::2]etykiety należy ukryć.
jolvi

To nie działa z matplotlib.finance.candlestick2
BCR

@BCR może być tak, że niektóre xticklabels są właśnie ustawione ''tak, że kiedy je zapętlasz, robisz xticklabels, które są puste niewidoczne (co nie miałoby wpływu na wizualizację, ale może oznaczać, że nie ciągniesz prawidłowe etykiety). Możesz spróbować: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf

15

To jest stary temat, ale od czasu do czasu potykam się o to i stworzyłem tę funkcję. To bardzo wygodne:

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)

Jednym z ostrzeżeń związanych z kontrolowaniem taktów jest to, że nie cieszy się już interaktywną automatyczną aktualizacją maksymalnej skali po dodaniu linii. Więc zrób

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

i ponownie uruchom funkcję resadjust.


11

Opracowałem nieeleganckie rozwiązanie. Rozważ, że mamy oś X, a także listę etykiet dla każdego punktu w X.

Przykład:
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']
Powiedzmy, że chcę pokazywać etykiety z kleszczami tylko dla „feb” i „Jun”
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Dobrze, teraz mamy fałszywą listę etykiet. Najpierw nakreśliliśmy oryginalną wersję.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Teraz zmodyfikowana wersja.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

6

jeśli chcesz tylko ustawić odstęp prostą wkładką z minimalną płytą grzewczą:

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

działa również łatwo w przypadku drobnych kleszczy:

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

trochę kęs, ale dość kompaktowy


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

plt.xticks(xmarks)

To zadziałało dla mnie

jeśli chcesz zaznaczyć od [1,5] (od 1 do 5 włącznie), zamień

length = 5

1
fyi, możesz po prostu pisać xmarks = range(1, length+1, 1). całkiem pewne, że lista jest zbędna.
Neal

2

Implementacja Pure Python

Poniżej znajduje się czysta implementacja żądanej funkcjonalności w języku Python, która obsługuje dowolne szeregi liczbowe (int lub float) o wartościach dodatnich, ujemnych lub mieszanych i pozwala użytkownikowi określić żądany rozmiar kroku:

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)

Przykładowe dane wyjściowe

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

Przykładowe użycie

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

Wykres użycia próbki

Zauważ, że oś x ma wartości całkowite równomiernie rozmieszczone o 5, podczas gdy oś y ma inny przedział ( matplotlibzachowanie domyślne, ponieważ tiki nie zostały określone).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.