2015-04-05 13 views
8

I nur ein Teil des Arrays plotten möchte, x Befestigungsteil, aber y Teil automatische Skalierung zu lassen. Ich habe versucht, wie unten gezeigt, aber es funktioniert nicht.Matplotlib - Befestigungs x Achsenskala und automatische Skalierung der Y-Achse

Irgendwelche Vorschläge?

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

Antwort

5

Autoscaling verwendet immer die gesamte Bandbreite der Daten, so dass die y-Achse wird durch volles Ausmaß der y-Daten skaliert, nicht nur, was innerhalb der x-Grenzen ist.

Wenn Sie eine Teilmenge der Daten angezeigt werden mögen, dann ist es wahrscheinlich am einfachsten nur diese Teilmenge zu plotten:

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

ich diese Idee auch hatte, aber ich wusste nicht, dass in Python so einfach Subset machen war :) – Pygmalion

8

Während Joe Kington sicherlich die vernünftigste Antwort schlägt, wenn er empfiehlt, dass nur die notwendigen Daten geplottet werden, gibt es Situationen, in denen es am besten wäre, alle Daten zu plotten und nur auf einen bestimmten Abschnitt zu zoomen. Außerdem wäre es schön, eine „autoscale_y“ Funktion zu haben, die nur die Achsen Objekt erfordert (dh im Gegensatz zu der Antwort here, die direkte Nutzung der Daten erfordert.)

Hier ist eine Funktion, die nur die y- neu skaliert Achse auf der Grundlage der Daten, die im sichtbaren x-Region:

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) 

das ist etwas, wie ein Hack, und wird wahrscheinlich nicht in vielen Situationen arbeiten, aber für eine einfache Handlung, es funktioniert gut.

Hier ist ein einfaches Beispiel mit dieser Funktion ist:

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

Das ist großartig, aber es schlägt fehl, wenn das Diagramm axhline() s enthält. Ich werde versuchen, es zu tunen, weil es genau das ist, was ich will. –

+0

I ersetzt y_displayed = km [((xd> = lo) & (xd <= Hallo))] mit wenn len (xd) == 2 und xd [0] == 0.0 und xd [1] == 1,0: y_displayed = km #special Fall zu behandeln axhline anderes: y_displayed = km [((xd> = lo) & (xd <= Hallo))] –

+0

Ja, es ist schade, dass es keine autoscale_axis ist, wahrscheinlich könnte es sein, bereits in der letzten Aktualisierung von Matplotlib implementiert. Danke für deinen Beitrag, ich benutze es und funktioniert super! Aber auch, wenn Sie den gesamten Bereich der Werte plotten möchten und dann vergrößern, @ Joe Kinton ‚s Lösung ist einfacher durch alle Bereich auf der linken Seite durch und die maskierten Werte auf der rechten Seite ein Plotten. – Hugo

Verwandte Themen