2013-05-29 4 views
8

Я делаю график рассеяния с квадратным маркером в Matplotlib как этот:Выбор размера маркера в Matplotlib

small_marker.

Я хочу, чтобы достичь чего-то вроде этого:

enter image description here

Это означает, что я должен регулировать размер маркера и размер/соотношение фигуры таким образом, что не существует не белое пространство между маркерами. Кроме того, должно быть маркером на единицу индекса (х и у оба целые числа), так что если у идет от 60 до 100, не должно быть 40 маркеров в у направлении. В настоящий момент я настраиваю его вручную. Любая идея о том, что является лучшим способом достичь этого?

+5

Используйте 'plt.imshow' или' plt.pcolor' вместо этого! –

+0

Заполните пустые позиции данных с помощью 'np.nan' или используйте маску. Как colormap обрабатывает плохие значения, управляется с помощью 'set_bad' – tacaswell

+0

@tcaswell, у меня нет пустых данных – elyase

ответ

7

Я нашел два способа идти об этом:

Первый основан на this answer. В основном, вы определяете количество пикселей между соседними точками данных и используете его для установки размера маркера. Площадь маркера составляет scatter.

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) 

Недостатком этого первого подхода является то, что символы перекрываются. Я не смог найти недостаток в этом подходе. Я мог бы вручную настроить s1 для

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

, чтобы дать лучшие результаты, но я не мог определить логику 13..

Следовательно, второй подход основан на this answer. Здесь индивидуальные квадраты рисуются на участке и соответствующим образом. В некотором смысле это руководство диаграмма рассеяния (цикл используется для построения фигуры), поэтому в зависимости от набора данных это может занять некоторое время.

Этот подход использует patches вместо scatter, так что не забудьте включить

from matplotlib.patches import Rectangle 

Опять же, с теми же данными точками:

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

Один комментарий на Rectangle: координаты являются нижний левый угол, следовательно x-h/2.
Этот подход дает связанные прямоугольники. Если бы я внимательно посмотрел на результат здесь, они все еще, казалось, перекрывались на один пиксель - опять же, я не уверен, что этому может помочь.

+0

Я только что нашел [этот сайт] (http://www.physics.ucdavis.edu/~dwittman/Matplotlib-examples/). В разделе * More Spatial Binning * указан другой вариант, который может быть альтернативой, @elyase – Schorsch

Смежные вопросы