De “Vinkfrequentie” wijzigen op X of Y-as in Matplotlib?

Ik probeer te bepalen hoe Python mijn gegevens plotsert.

Zeg

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

en

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

Dan zou ik doen:

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

en de x-as ‘tekenen zijn uitgezet in intervallen van 5. Is er een manier om het te laten zien van intervallen van 1?


Antwoord 1, Autoriteit 100%

U kunt expliciet ingesteld waar u markeringen wilt aanklikken met plt.xticks:

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

Bijvoorbeeld,

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.arangewerd gebruikt in plaats van Python’s rangeFunctie voor het geval min(x)EN max(x)zijn drijvers in plaats van ints.)


De plt.plot(of ax.plot) Functie stelt automatisch standaard xen ylimieten in . Als u die limieten wilt behouden, kunt u de stappen van de vinkjes wijzigen, dan kunt u ax.get_xlim()gebruiken om te ontdekken welke limieten Matplotlib al heeft ingesteld.

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

De standaard tick-formatter zou een behoorlijke klus moeten klaren door de tick-waarden af te ronden tot een redelijk aantal significante cijfers. Als u echter meer controle over het formaat wilt hebben, kunt u uw eigen formatter definiëren. Bijvoorbeeld,

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

Hier is een uitvoerbaar voorbeeld:

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

Antwoord 2, autoriteit 34%

Een andere benadering is om de aslocator in te stellen:

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

Er zijn verschillende soorten zoeker, afhankelijk van uw behoeften.

Hier is een volledig voorbeeld:

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

Antwoord 3, autoriteit 22%

Ik vind deze oplossing leuk (uit het 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()

Deze oplossing geeft u expliciete controle over de vinkafstand via het nummer dat wordt gegeven aan ticker.MultipleLocater(), maakt automatische limietbepaling mogelijk en is eenvoudig te lezen.


Antwoord 4, Autoriteit 16%

Als iemand geïnteresseerd is in een algemene one-liner, krijgt u eenvoudig de huidige teken en gebruikt u deze om de nieuwe teken in te stellen door elke andere vinkje te bemonsteren.

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

Antwoord 5, Autoriteit 5%

Dit is een beetje hacky, maar verreweg het schoonste / gemakkelijkste om het voorbeeld te begrijpen dat ik dit heb gevonden. Het is van een antwoord op dus hier:

Schoonbare manier om elke NTH Tick te verbergen Label in Matplotlib ColorBar?

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

Dan kunt u de labels instellen die ze instellen om zichtbaar te zijn of niet afhankelijk van de gewenste dichtheid.

EDIT: Merk op dat Soms MatPLotlib Labels == ''instelt, dus het lijkt erop dat een label niet aanwezig is, wanneer het in feite is en gewoon niets toont. Om ervoor te zorgen dat u loopt door daadwerkelijke zichtbare labels, kunt u het proberen:

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)

Antwoord 6, autoriteit 3%

als je alleen de tussenruimte wilt instellen op een eenvoudige one-liner met minimale boilerplate:

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

werkt ook gemakkelijk voor kleine teken:

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

een beetje een mondvol, maar vrij compact


Antwoord 7, autoriteit 2%

Dit is een oud onderwerp, maar ik struikel hier zo nu en dan over en heb deze functie gemaakt. Het is erg handig:

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)

Een voorbehoud bij het op deze manier beheersen van de teken is dat men niet langer geniet van de interactieve automagische update van de maximale schaal na een toegevoegde regel. Doe dan

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

en voer de heraanpassingsfunctie opnieuw uit.


Antwoord 8, autoriteit 2%

Ik heb een onelegante oplossing ontwikkeld. Bedenk dat we de X-as hebben en ook een lijst met labels voor elk punt in X.

Voorbeeld:

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

Laten we zeggen dat ik teken labels alleen voor ‘feb’s’ en ‘jun’ wil laten zien

xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)

Goed, nu hebben we een valse lijst met labels. Ten eerste hebben we de originele versie geplot.

plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()

Nu, de gewijzigde versie.

plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

Antwoord 9

Pure Python-implementatie

Hieronder is een pure Python-implementatie van de gewenste functionaliteit die elke numerieke serie (INT of FLATER) met positieve, negatieve of gemengde waarden verwerkt en zorgt ervoor dat de gebruiker de gewenste stapgrootte opgeven:

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)

Voorbeelduitvoer

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

Sample-gebruik

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

Mededeling De X-as heeft gehele getalwaarden al gelijkmatig op afstand met 5, terwijl de Y-as een ander interval heeft (de matplotlibstandaardgedrag, omdat de teken niet is opgegeven).


Antwoord 10

xmarks=[i for i in range(1,length+1,1)]
plt.xticks(xmarks)

Dit werkte voor mij

Als u tekent tussen [1,5] (1 en 5 inclusief), vervangt u

length = 5

Antwoord 11

Sinds Geen van de bovenstaande oplossingen werkte voor mijn usecase, hier geef ik een oplossing met behulp van None(woordspeling!) die kan worden aangepast aan een grote verscheidenheid aan scenario’s.

Hier is een monster-stuk code dat rommelige teken op zowel xen yassen produceert.

# Note the super cluttered ticks on both X and Y axis.
# inputs
x = np.arange(1, 101)
y = x * np.log(x) 
fig = plt.figure()     # create figure
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xticks(x)        # set xtick values
ax.set_yticks(y)        # set ytick values
plt.show()

Nu ruimen we de rommel op met een nieuwe plot die alleen een schaarse reeks waarden op zowel de x- als de y-as als vinkjes laat zien.

# inputs
x = np.arange(1, 101)
y = x * np.log(x)
fig = plt.figure()       # create figure
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xticks(x)
ax.set_yticks(y)
# which values need to be shown?
# here, we show every third value from `x` and `y`
show_every = 3
sparse_xticks = [None] * x.shape[0]
sparse_xticks[::show_every] = x[::show_every]
sparse_yticks = [None] * y.shape[0]
sparse_yticks[::show_every] = y[::show_every]
ax.set_xticklabels(sparse_xticks, fontsize=6)   # set sparse xtick values
ax.set_yticklabels(sparse_yticks, fontsize=6)   # set sparse ytick values
plt.show()

Afhankelijk van de usecase, kan men de bovenstaande code eenvoudig aanpassen door show_everyte veranderen en die te gebruiken voor het nemen van steekproeven van tick-waarden voor X of Y of beide assen.

Als deze op stapgrootte gebaseerde oplossing niet past, kan men ook de waarden van sparse_xticksof sparse_yticksmet onregelmatige tussenpozen invullen, als dat is wat gewenst is.


Antwoord 12

Generaliseerbare één voering, met alleen Numpy geïmporteerd:

import numpy as np
ax.set_xticks(np.arange(min(ax.get_xticks()),max(ax.get_xticks()),1));

Other episodes