2012-01-31 133 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