2015-04-05 50 views
8

Chciałbym wykreślić tylko część tablicy, ustalając x część, ale pozwalając y część autoskalowania. Próbowałem, jak pokazano poniżej, ale to nie działa.Matplotlib - ustalenie osi x osi i autoskalowania y

Wszelkie sugestie?

import numpy as np 
import matplotlib.pyplot as plt 

data=[np.arange(0,101,1),300-0.1*np.arange(0,101,1)] 

plt.figure() 

plt.scatter(data[0], data[1]) 
plt.xlim([50,100]) 
plt.autoscale(enable=True, axis='y') 

plt.show() 

Odpowiedz

5

AutoScaling zawsze wykorzystuje pełen zakres danych, więc oś y jest skalowany przez pełnym zakresie Y danych, a nie tylko to, co znajduje się w obrębie x terminów.

Jeśli chcesz wyświetlić podzbiór danych, to chyba najłatwiej wykreślić tylko ten podzbiór:

import numpy as np 
import matplotlib.pyplot as plt 

x, y = np.arange(0,101,1) ,300 - 0.1*np.arange(0,101,1) 
mask = (x >= 50) & (x <= 100) 

fig, ax = plt.subplots() 
ax.scatter(x[mask], y[mask]) 

plt.show() 
+0

Ja też miał ten pomysł, ale nie wiedziałem, że co podzbiór było takie proste w Pythonie :) – Pygmalion

8

Podczas Joe Kington pewno proponuje odpowiedź najrozsądniejsze kiedy zaleca, aby tylko niezbędnych danych być wykreślone, są sytuacje, w których najlepiej byłoby wydrukować wszystkie dane i po prostu powiększyć do pewnej sekcji. Dodatkowo, byłoby miło mieć funkcję "autoskalii", która wymaga tylko obiektu osi (tj. W przeciwieństwie do odpowiedzi here, która wymaga bezpośredniego użycia danych.)

Oto funkcja, która po prostu przeskalowuje y- oś opiera się na danych, które są w widzialnym x regionie:

def autoscale_y(ax,margin=0.1): 
    """This function rescales the y-axis based on the data that is visible given the current xlim of the axis. 
    ax -- a matplotlib axes object 
    margin -- the fraction of the total height of the y-data to pad the upper and lower ylims""" 

    import numpy as np 

    def get_bottom_top(line): 
     xd = line.get_xdata() 
     yd = line.get_ydata() 
     lo,hi = ax.get_xlim() 
     y_displayed = yd[((xd>lo) & (xd<hi))] 
     h = np.max(y_displayed) - np.min(y_displayed) 
     bot = np.min(y_displayed)-margin*h 
     top = np.max(y_displayed)+margin*h 
     return bot,top 

    lines = ax.get_lines() 
    bot,top = np.inf, -np.inf 

    for line in lines: 
     new_bot, new_top = get_bottom_top(line) 
     if new_bot < bot: bot = new_bot 
     if new_top > top: top = new_top 

    ax.set_ylim(bot,top) 

to jest coś hack, i prawdopodobnie nie będzie pracować w wielu sytuacjach, ale dla prostego wykresu, to działa dobrze.

Oto prosty przykład przy użyciu tej funkcji:

import numpy as np 
import matplotlib.pyplot as plt 

x = np.linspace(-100,100,1000) 
y = x**2 + np.cos(x)*100 

fig,axs = plt.subplots(1,2,figsize=(8,5)) 

for ax in axs: 
    ax.plot(x,y) 
    ax.plot(x,y*2) 
    ax.plot(x,y*10) 
    ax.set_xlim(-10,10) 

autoscale_y(axs[1]) 

axs[0].set_title('Rescaled x-axis') 
axs[1].set_title('Rescaled x-axis\nand used "autoscale_y"') 

plt.show() 

enter image description here

+0

To jest wielki, ale zawiedzie, jeśli wątek zawiera w sobie axhline(). Postaram się go dostroić, ponieważ dokładnie tego chcę. –

+0

I otrzymuje y_displayed = m [((xd> = lo) i (XD = lo) & (xd <= hi))] –

+0

Tak, szkoda, że ​​nie ma autoskalości, prawdopodobnie to może być już zaimplementowane w najnowszej aktualizacji matplotlib. Dziękuję za Twój wkład, używam go i działa świetnie! Jednak nawet jeśli chcesz wykreślić cały zakres wartości, a następnie powiększyć, rozwiązanie @Joe Kintona jest prostsze, wykreślając cały zakres na lewym panelu i zamaskowane wartości na prawym. – Hugo

Powiązane problemy