简体   繁体   English

Python散点图。标记的大小和样式

[英]Python scatter plot. Size and style of the marker

I have a set of data that I want to show as a scatter plot. 我有一组数据要显示为散点图。 I want each point to be plotted as a square of size dx . 我希望将每个点绘制为大小为dx的正方形。

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

The problem is that the size s that the scatter function read is in points^2. 问题是分散函数读取的大小为s ^ 2。 What I'd like is having each point represented by a square of area dx^2, where this area is in 'real' units, the plot units. 我想要的是每个点由面积dx ^ 2的平方表示,其中该区域是“实际”单位,即绘图单位。 I hope you can get this point. 我希望你能明白这一点。

I also have another question. 我还有另一个问题。 The scatter function plots the markers with a black border, how can I drop this option and have no border at all? 散点函数用黑色边框绘制标记,如何删除此选项并且根本没有边框?

Translate from user data coordinate system to display coordinate system. 用户数据坐标系转换为显示坐标系。

and use edgecolors='none' to plot faces with no outlines. 并使用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')

If you want markers that resize with the figure size, you can use patches: 如果您想要使用图形大小调整大小的标记,可以使用修补程序:

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

在此输入图像描述

Note that: 注意:

  1. The squares are not centered at (x,y) . 正方形不以(x,y)为中心。 x,y are actually the coords of the square lower left. x,y实际上是左下方的坐标。 I let it this way to simplify my code. 我这样简化我的代码。 You should use (x + dx/2, y + dx/2) . 你应该使用(x + dx/2, y + dx/2)
  2. The color is get from the hot colormap. 颜色来自热色图。 I used z**2 to give colors. 我用z ** 2来给出颜色。 you should also adapt this to your needs 你也应该根据自己的需要进行调整

Finally for your second question. 最后是你的第二个问题。 You can get the border of the scatter marks out using the keyword arguments edgecolor or edgecolors . 您可以使用关键字参数edgecoloredgecolors来获取散点图的边框。 These are a matplotlib color argument or a sequence of rgba tuples, respectively. 它们分别是matplotlib颜色参数或rgba元组序列。 If you set the parameter to 'None', borders are not draw. 如果将参数设置为“无”,则不绘制边框。

I think we can do it better with a collection of patches. 我想我们可以通过一系列补丁来做得更好。 According to documents: 根据文件:

This (PatchCollection) makes it easier to assign a color map to a heterogeneous collection of patches. 这个(PatchCollection)可以更容易地将颜色映射分配给异构的补丁集合。

This also may improve plotting speed , since PatchCollection will draw faster than a large number of patches. 这也可以提高绘图速度 ,因为PatchCollection将比大量补丁绘制得更快。

Suppose you want to plot a scatter of circles with given radius in data unit: 假设您要在数据单元中绘制具有给定半径的圆的散布:

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

All the arguments and keywords (except marker ) of scatter function would work in similar way. scatter函数的所有参数和关键字( marker除外)都可以以类似的方式工作。 I've write a gist including circles , ellipses and squares / rectangles . 我写了一个要点,包括圆形椭圆形正方形 / 矩形 If you want a collection of other shape, you could modify it yourself. 如果你想要一个其他形状的集合,你可以自己修改它。

If you want to plot a colorbar just run colorbar() or pass the returned collection object to colorbar function. 如果要绘制颜色条,只需运行colorbar()或将返回的集合对象传递给colorbar函数。

An example: 一个例子:

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)

Output: 输出:

示例图

To make this Python 3 compatible, I added the following snippet of code 为了使Python 3兼容,我添加了以下代码片段

try:
    basestring
except NameError:
    basestring = str

from

How to check if variable is string with python 2 and 3 compatibility 如何检查变量是否是python 2和3兼容性的字符串

This is necessary because basestring is not available in Python 3. In Python 2, the purpose of basestring was to include both str and unicode . 这是必要的,因为在Python 3中没有basestring 。在Python 2中, basestring的目的是包括strunicode In Python 3 there is no distinction between str and unicode , and it's just str . 在Python 3中, strunicode之间没有区别,它只是str

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM