Scatter plot de Python. Taille et style du marqueur

j'ai un ensemble de données que je veux montrer, comme un nuage de points. Je veux que chaque point soit tracé comme un carré de taille 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')

le problème est que la taille s que la fonction de dispersion lire est en points^2. Ce que j'aimerais c'est que chaque point soit représenté par un carré de superficie dx^2, où cette superficie est en unités "réelles", les unités de parcelle. J'espère que vous pouvez obtenir ce point.

j'ai aussi une autre question. L'éparpillement la fonction trace les marqueurs avec une bordure noire, comment puis-je laisser tomber cette option et n'ont pas de frontière?

36
demandé sur Brian 2012-01-31 18:50:00

4 réponses

Traduire de données utilisateur système de coordonnées à affichage système de coordonnées.

et utilisez edgecolors='none' pour tracer les visages sans contours.

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')
38
répondu remosu 2012-01-31 15:58:48

si vous voulez des marqueurs qui redimensionnent avec la taille de la figure, vous pouvez utiliser des 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()

enter image description here

noter que:

  1. les carrés ne sont pas centrés à (x,y) . x,y sont en fait les coords de le carré en bas à gauche. Je l'ai laissé ainsi pour simplifier mon code. Vous devrait utiliser (x + dx/2, y + dx/2) .
  2. la couleur provient du colormap chaud. J'ai utilisé z* * 2 pour donner couleur. vous devez également l'adapter à vos besoins

enfin votre deuxième question. Vous pouvez obtenir le bord des scatter marks en utilisant les arguments de mots clés edgecolor ou edgecolors . Il s'agit d'un argument de couleur matplotlib ou une séquence de tuples rgba, respectivement. Si vous définissez le paramètre à 'None', les bordures ne sont pas draw.

21
répondu joaquin 2012-01-31 16:04:29

je pense que nous pouvons faire mieux avec une collection de patchs. Selon les documents:

ceci (PatchCollection) rend plus facile d'assigner une carte de couleur à un hétérogène collection de patchs.

cela peut également améliorer vitesse de pointage , car PatchCollection sera dessiner plus vite qu'un grand nombre de correctifs.

supposez que vous vous voulez tracer une dispersion de cercles avec un rayon donné dans l'Unité de données:

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

tous les arguments et mots clés (sauf marker ) de la fonction scatter fonctionneraient de la même manière. J'ai écris un gist y compris cercles , ellipses et carrés / rectangles . Si vous voulez une collection d'autres en forme, vous pourrait modifier vous-même.

si vous voulez tracer un colorbar juste exécuter colorbar() ou passer l'objet de collection retourné à colorbar fonction.

un exemple:

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)

sortie:

Example Figure

17
répondu Syrtis Major 2016-09-25 02:59:08

pour rendre ce Python 3 compatible, j'ai ajouté l'extrait suivant du code

try:
    basestring
except NameError:
    basestring = str

de

Comment vérifier si la variable est une chaîne de compatibilité avec python 2 et 3

C'est nécessaire car basestring n'est pas disponible en Python 3. Dans Python 2, le but de basestring était d'inclure à la fois str et unicode . En Python 3 Il n'y a pas de distinction entre str et unicode , et c'est juste str .

0
répondu Michael Wood-Vasey 2017-05-23 12:03:08