2013-05-29 10 views
8

robie wykres punktowy z kwadratowego markera w matplotlib jak ten:Wybór rozmiaru marker w matplotlib

small_marker.

chcę osiągnąć coś takiego:

enter image description here

Czyli muszę dostosować rozmiar znacznika oraz wielkość/stosunek postać w taki sposób, że nie istnieją żadne spacje między markerami. Ponadto nie powinno być znacznika na urządzeniu wskazującym (x i Y są obie liczby), tak jeśli Y przechodzi od 60 do 100, nie powinno być 40 markerów Y kierunku. W tej chwili dostaję go ręcznie. Masz pomysł, jaki jest najlepszy sposób, aby to osiągnąć?

+5

Zamiast tego użyj 'plt.imshow' lub' plt.pcolor'! –

+0

Wypełnij puste pozycje danych za pomocą 'np.nan' lub użyj zamaskowanej tablicy. W jaki sposób koszmar obsługuje złe wartości jest kontrolowany przez 'set_bad' – tacaswell

+0

@ tcaswell, nie mam pustych danych – elyase

Odpowiedz

7

Znalazłem dwa sposoby, aby przejść na ten temat:

Pierwsza jest oparta na this answer. Zasadniczo określasz liczbę pikseli pomiędzy sąsiednimi punktami danych i używasz go do ustawienia rozmiaru znacznika. Rozmiar znacznika w scatter podano jako obszar.

fig = plt.figure() 
ax = fig.add_subplot(111, aspect='equal') 

# initialize a plot to determine the distance between the data points in pixel:  
x = [1, 2, 3, 4, 2, 3, 3] 
y = [0, 0, 0, 0, 1, 1, 2] 
s = 0.0 
points = ax.scatter(x,y,s=s,marker='s') 
ax.axis([min(x)-1., max(x)+1., min(y)-1., max(y)+1.]) 

# retrieve the pixel information: 
xy_pixels = ax.transData.transform(np.vstack([x,y]).T) 
xpix, ypix = xy_pixels.T 

# In matplotlib, 0,0 is the lower left corner, whereas it's usually the upper 
# right for most image software, so we'll flip the y-coords 
width, height = fig.canvas.get_width_height() 
ypix = height - ypix 

# this assumes that your data-points are equally spaced 
s1 = xpix[1]-xpix[0] 

points = ax.scatter(x,y,s=s1**2.,marker='s',edgecolors='none') 
ax.axis([min(x)-1., max(x)+1., min(y)-1., max(y)+1.]) 

fig.savefig('test.png', dpi=fig.dpi) 

Wadą tego pierwszego podejścia jest to, że symbole zachodzą na siebie. Nie mogłem znaleźć wady w podejściu. Mógłbym ręcznego dostrojenia s1 do

s1 = xpix[1]-xpix[0] - 13. 

dać lepsze rezultaty, ale nie mogłem określić logika 13..

Stąd drugie podejście oparte na this answer. Tutaj poszczególne kwadraty są rysowane na działce i odpowiednio dobrane. W pewnym sensie jest to wykres rozproszenia (pętla służy do skonstruowania figury), więc w zależności od zestawu danych może to chwilę potrwać.

Podejście to wykorzystuje patches zamiast scatter, więc należy pamiętać o

from matplotlib.patches import Rectangle 

Ponownie, z tymi samymi danymi punktami:

x = [1, 2, 3, 4, 2, 3, 3] 
y = [0, 0, 0, 0, 1, 1, 2] 
z = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] # in your case, this is data 
dx = [x[1]-x[0]]*len(x) # assuming equally spaced data-points 

# you can use the colormap like this in your case: 
# cmap = plt.cm.hot 

fig = plt.figure() 
ax = fig.add_subplot(111, aspect='equal') 
ax.axis([min(x)-1., max(x)+1., min(y)-1., max(y)+1.]) 

for x, y, c, h in zip(x, y, z, dx): 
    ax.add_artist(Rectangle(xy=(x-h/2., y-h/2.), 
        color=c,    # or, in your case: color=cmap(c)     
        width=h, height=h)) # Gives a square of area h*h 

fig.savefig('test.png') 

Jeden komentarz na Rectangle: The współrzędnych są dolny lewy róg, stąd x-h/2. Takie podejście zapewnia połączone prostokąty. Jeśli przyjrzałem się dokładniej wynikom wyjściowym, nadal wydawały się pokrywać jeden piksel - znowu nie jestem pewien, czy można temu zaradzić.

+0

Właśnie znalazłem [tę stronę] (http://www.physics.ucdavis.edu/~dwittman/Matplotlib-examples/). W obszarze * More Przestrzenne Binning * zaznaczono inną opcję, która może być alternatywą @elyase – Schorsch