web-dev-qa-db-fra.com

Python nuage de points. Taille et style du marqueur

J'ai un ensemble de données que je souhaite afficher sous forme de 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 scatter lit est en points ^ 2. Ce que j'aimerais, c'est que chaque point soit représenté par un carré de la zone dx ^ 2, où cette zone est en unités "réelles", les unités de tracé. J'espère que vous pourrez comprendre ce point.

J'ai également une autre question. La fonction scatter trace les marqueurs avec une bordure noire, comment puis-je supprimer cette option et ne pas avoir de bordure du tout?

39
Brian

Traduisez du système de coordonnées données utilisateur au système de coordonnées affichage.

et utilisez edgecolors = 'none' pour tracer des 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')
42
remosu

Si vous voulez des marqueurs qui redimensionnent avec la taille de la figure, vous pouvez utiliser des correctifs:

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

Notez que:

  1. Les carrés ne sont pas centrés sur (x,y). x, y sont en fait les coordonnées du carré en bas à gauche. Je le laisse de cette façon pour simplifier mon code. Tu devrais utiliser (x + dx/2, y + dx/2).
  2. La couleur provient de la palette de couleurs chaude. J'ai utilisé z ** 2 pour donner des couleurs. vous devez également l'adapter à vos besoins

Enfin pour votre deuxième question. Vous pouvez obtenir la bordure des points de dispersion en utilisant les arguments de mot clé edgecolor ou edgecolors. Il s'agit respectivement d'un argument de couleur matplotlib ou d'une séquence de tuples rgba. Si vous définissez le paramètre sur "Aucun", les bordures ne sont pas dessinées.

21
joaquin

Je pense que nous pouvons le faire mieux avec une collection de correctifs. Selon les documents:

Cette (PatchCollection) facilite l'attribution d'une palette de couleurs à une collection hétérogène de correctifs.

Cela peut également améliorer la vitesse de traçage , car PatchCollection dessinera plus rapidement qu'un grand nombre de correctifs.

Supposons que vous souhaitiez 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 écrit un ( Gist incluant cercles , ellipses et carrés / rectangles . Si vous voulez une collection d'une autre forme, vous pouvez la modifier vous-même.

Si vous voulez tracer une colorbar exécutez simplement colorbar() ou passez l'objet de collection retourné à la fonction colorbar.

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

18
Syrtis Major

Pour rendre cela Python 3 compatible, j'ai ajouté l'extrait de code suivant

try:
    basestring
except NameError:
    basestring = str

de

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

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

0
Michael Wood-Vasey