2012-01-31 297 views
33

我有一組數據,我想將其顯示爲散點圖。我希望將每個點繪製爲尺寸爲dx的平方。Python散點圖。標記的大小和樣式

  x = [0.5,0.1,0.3] 
      y = [0.2,0.7,0.8] 
      z = [10.,15.,12.] 
      dx = [0.05,0.2,0.1] 

      scatter(x,y,c=z,s=dx,marker='s') 

問題是散佈函數讀取的大小爲s爲點數^ 2。我想要的是每個點由一個面積爲dx^2的平方塊表示,其中這個面積是以「實際」單位爲單位的。我希望你能明白這一點。

我也有另一個問題。分散函數用黑色邊框繪製標記,我怎樣才能放棄這個選項並且根本沒有邊框?

回答

37

翻譯用戶數據座標系到顯示屏座標系。

並使用edgecolors ='none'來繪製沒有輪廓的面。

import numpy as np 

fig = figure() 
ax = fig.add_subplot(111) 
dx_in_points = np.diff(ax.transData.transform(zip([0]*len(dx), dx))) 
scatter(x,y,c=z,s=dx_in_points**2,marker='s', edgecolors='none') 
+7

這不會在*繪圖單位*中繪製正方形作爲OP請求,而是固定大小的正方形不會調整大小(例如,通過手動更改圖形框的大小) – joaquin 2012-01-31 16:18:38

+1

這可能是一個愚蠢的問題,但是如何更改代碼如果以上dx是不是一個數組,但它的每一個點(X,Y,Z)是相同的。此外,什麼纔是我真正需要使用add_subplot? – Brian 2012-04-25 15:44:00

+1

你是怎麼找到的'edgecolors'說法? – Dror 2015-08-24 13:15:12

20

如果你想與圖形大小調整的標記,你可以使用補丁:

from matplotlib import pyplot as plt 
from matplotlib.patches import Rectangle 

x = [0.5, 0.1, 0.3] 
y = [0.2 ,0.7, 0.8] 
z = [10, 15, 12] 
dx = [0.05, 0.2, 0.1] 

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

for x, y, c, h in zip(x, y, z, dx): 
    ax.add_artist(Rectangle(xy=(x, y), 
        color=cmap(c**2),  # I did c**2 to get nice colors from your numbers 
        width=h, height=h))  # Gives a square of area h*h 

plt.show() 

enter image description here

需要注意的是:

  1. 方格是沒有(x,y)中心。 x,y實際上是方形左下方的 的座標。我通過這種方式來簡化我的代碼。您 應該使用(x + dx/2, y + dx/2)
  2. 顏色從熱色圖中獲得。我用z ** 2來給顏色。 你也應該適應這個以您的需求

最後你的第二個問題。您可以使用關鍵字參數edgecoloredgecolors獲取分散標記的邊界。這些分別是matplotlib顏色參數或rgba元組序列。如果將該參數設置爲「無」,則不會繪製邊框。

17

我想我們可以用補丁集合做得更好。 根據文件規定:

這(PatchCollection)使得它更容易爲彩色地圖分配到一個異類 集合補丁的。

這也可能會提高繪圖速度,因爲PatchCollection會將 繪製得比大量的補丁快。

假設要繪製圓的散射與數據單元給出半徑:

def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): 
    """ 
    Make a scatter of circles plot of x vs y, where x and y are sequence 
    like objects of the same lengths. The size of circles are in data scale. 

    Parameters 
    ---------- 
    x,y : scalar or array_like, shape (n,) 
     Input data 
    s : scalar or array_like, shape (n,) 
     Radius of circle in data unit. 
    c : color or sequence of color, optional, default : 'b' 
     `c` can be a single color format string, or a sequence of color 
     specifications of length `N`, or a sequence of `N` numbers to be 
     mapped to colors using the `cmap` and `norm` specified via kwargs. 
     Note that `c` should not be a single numeric RGB or RGBA sequence 
     because that is indistinguishable from an array of values 
     to be colormapped. (If you insist, use `color` instead.) 
     `c` can be a 2-D array in which the rows are RGB or RGBA, however. 
    vmin, vmax : scalar, optional, default: None 
     `vmin` and `vmax` are used in conjunction with `norm` to normalize 
     luminance data. If either are `None`, the min and max of the 
     color array is used. 
    kwargs : `~matplotlib.collections.Collection` properties 
     Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), 
     norm, cmap, transform, etc. 

    Returns 
    ------- 
    paths : `~matplotlib.collections.PathCollection` 

    Examples 
    -------- 
    a = np.arange(11) 
    circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none') 
    plt.colorbar() 

    License 
    -------- 
    This code is under [The BSD 3-Clause License] 
    (http://opensource.org/licenses/BSD-3-Clause) 
    """ 
    import numpy as np 
    import matplotlib.pyplot as plt 
    from matplotlib.patches import Circle 
    from matplotlib.collections import PatchCollection 

    if np.isscalar(c): 
     kwargs.setdefault('color', c) 
     c = None 
    if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc')) 
    if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec')) 
    if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls')) 
    if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw')) 

    patches = [Circle((x_, y_), s_) for x_, y_, s_ in np.broadcast(x, y, s)] 
    collection = PatchCollection(patches, **kwargs) 
    if c is not None: 
     collection.set_array(np.asarray(c)) 
     collection.set_clim(vmin, vmax) 

    ax = plt.gca() 
    ax.add_collection(collection) 
    ax.autoscale_view() 
    if c is not None: 
     plt.sci(collection) 
    return collection 

所有參數和scatter功能的關鍵字(除了)將在類似的方式工作。 我已經寫了gist包括橢圓廣場/矩形。如果你想要一個其他形狀的集合,你可以自己修改它。

如果要繪製一條色條只需運行colorbar()或將返回的集合對象傳遞給colorbar函數。

一個例子:

from pylab import * 
figure(figsize=(6,4)) 
ax = subplot(aspect='equal') 

#plot a set of circle 
a = arange(11) 
out = circles(a, a, a*0.2, c=a, alpha=0.5, ec='none') 
colorbar() 

#plot one circle (the lower-right one) 
circles(1, 0, 0.4, 'r', ls='--', lw=5, fc='none', transform=ax.transAxes) 

xlim(0,10) 
ylim(0,10) 

輸出:

Example Figure

+1

我想在開源項目中使用你的函數,但不能這樣做,因爲默認情況下所有的SO代碼都在[CC BY-SA許可證](https://meta.stackexchange.com/a/12539/155787)中。你的代碼的許可證,最好是BSD類似的? – letmaik 2014-10-23 15:07:27

+1

@neo很高興知道,我不熟悉許可證,我認爲它應該與[matplotlib]保持一致(http://matplotlib.org/users/裏cense.html),因爲我剛剛基於'scatter'函數編寫了這段代碼。所以它應該是PSF什麼的? – 2014-10-24 06:24:39

+0

您的代碼片段不是matplotlib的衍生作品,因此您可以根據任何許可證授權您的代碼。我只會使用[BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause),它在Python世界中很常見。 – letmaik 2014-10-24 07:59:47

0

爲了使這個Python 3的兼容,我添加下面的代碼片斷

try: 
    basestring 
except NameError: 
    basestring = str 

How to check if variable is string with python 2 and 3 compatibility

這是必要的,因爲basestring不可用在Python 3.在Python 2,的basestring目的是包括strunicode。在Python 3中,strunicode之間沒有區別,它只是str