Zmień wartości na osi wykresu matplotlib imshow ()

89

Powiedzmy, że mam dane wejściowe:

data = np.random.normal(loc=100,scale=10,size=(500,1,32))
hist = np.ones((32,20)) # initialise hist
for z in range(32):
    hist[z],edges = np.histogram(data[:,0,z],bins=np.arange(80,122,2))

Mogę to wykreślić za pomocą imshow():

plt.imshow(hist,cmap='Reds')

uzyskiwanie:

wprowadź opis obrazu tutaj

Jednak wartości na osi X nie są zgodne z danymi wejściowymi (tj. Średnia ze 100, zakres od 80 do 122). Dlatego chciałbym zmienić oś X, aby pokazać wartości w edges.

Próbowałem:

ax = plt.gca()
ax.set_xlabel([80,122]) # range of values in edges
...
# this shifts the plot so that nothing is visible

i

ax.set_xticklabels(edges)
...
# this labels the axis but does not centre around the mean:

wprowadź opis obrazu tutaj

Jakieś pomysły, jak zmienić wartości osi, aby odzwierciedlić dane wejściowe, których używam?

atomh33ls
źródło
Użyj pcolorzamiast, imshowjak wspomniano w tej odpowiedzi .
Nirmal

Odpowiedzi:

142

xticklabelsStarałbym się unikać zmiany, jeśli to możliwe, w przeciwnym razie może to być bardzo mylące, jeśli na przykład przeplotujesz histogram dodatkowymi danymi.

Zdefiniowanie zakresu twojej siatki jest prawdopodobnie najlepsze i imshowmożna to zrobić, dodając extentsłowo kluczowe. W ten sposób osie są regulowane automatycznie. Jeśli chcesz zmienić etykiety, użyłbym set_xticksbyć może z jakimś formaterem. Bezpośrednia zmiana etykiet powinna być ostatecznością.

fig, ax = plt.subplots(figsize=(6,6))

ax.imshow(hist, cmap=plt.cm.Reds, interpolation='none', extent=[80,120,32,0])
ax.set_aspect(2) # you may also use am.imshow(..., aspect="auto") to restore the aspect ratio

wprowadź opis obrazu tutaj

Rutger Kassies
źródło
18
Warto również zauważyć, że interpolation="none"zastosowano tutaj znacznie dokładniejszą reprezentację rzeczywistych danych.
Hooked
4
Najbardziej przydatna odpowiedź; Użyłem go do sporządzenia kolorowego wykresu funkcji dwóch zmiennych (mianowicie danych sejsmicznych). Dodałem również opcję "aspekt = 'auto'" w imshow (), dzięki czemu mogę 'rozciągać i ściskać' wyświetlacz sejsmiczny.
Kurt Peek
10

Miałem podobny problem i Google wysyłał mnie do tego posta. Moje rozwiązanie było trochę inne i mniej kompaktowe, ale mam nadzieję, że może się to komuś przydać.

Pokazywanie obrazu za pomocą matplotlib.pyplot.imshow to zazwyczaj szybki sposób wyświetlania danych 2D. Jednak to domyślnie oznacza osie z liczbą pikseli. Jeśli kreślone dane 2D odpowiadają jakiejś jednolitej siatce zdefiniowanej przez tablice x i y, możesz użyć matplotlib.pyplot.xticks i matplotlib.pyplot.yticks, aby oznaczyć osie x i y przy użyciu wartości w tych tablicach. Powiążą one niektóre etykiety, odpowiadające rzeczywistym danym siatki, z liczbą pikseli na osiach. A robienie tego jest znacznie szybsze niż na przykład używanie czegoś takiego jak pcolor.

Oto próba tego z Twoimi danymi:

import matplotlib.pyplot as plt

# ... define 2D array hist as you did

plt.imshow(hist, cmap='Reds')
x = np.arange(80,122,2) # the grid to which your data corresponds
nx = x.shape[0]
no_labels = 7 # how many labels to see on axis x
step_x = int(nx / (no_labels - 1)) # step between consecutive labels
x_positions = np.arange(0,nx,step_x) # pixel count at label position
x_labels = x[::step_x] # labels you want to see
plt.xticks(x_positions, x_labels)
# in principle you can do the same for y, but it is not necessary in your case
rxs
źródło