web-dev-qa-db-fra.com

taille de marqueur de diagramme de dispersion de pyplot

Dans le document pyplot pour le nuage de points:

matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
                          vmin=None, vmax=None, alpha=None, linewidths=None,
                          faceted=True, verts=None, hold=None, **kwargs)

La taille du marqueur

s: taille en points ^ 2. C'est un scalaire ou un tableau de la même longueur que x et y.

Quel type d'unité est points^2? Qu'est-ce que ça veut dire? Est-ce que s=100 signifie 10 pixel x 10 pixel?

Fondamentalement, j'essaie de créer des diagrammes de dispersion avec différentes tailles de marqueur et je veux comprendre ce que signifie le nombre s.

292
LWZ

Cela peut être un moyen déroutant de définir la taille, mais vous spécifiez essentiellement la zone du marqueur. Cela signifie que pour doubler la largeur (ou la hauteur) du marqueur, vous devez augmenter le facteur s d'un facteur 4. [car A = W H => (2W) (2H) = 4A]

Cependant, il y a une raison pour laquelle la taille des marqueurs est définie de cette manière. En raison de la taille de la surface comme carré de la largeur, le fait de doubler la largeur semble en réalité augmenter la taille de plus d'un facteur 2 (en fait, il l'augmente d'un facteur 4). Pour voir cela, considérons les deux exemples suivants et le résultat qu'ils produisent.

# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

donne

enter image description here

Remarquez comment la taille augmente très rapidement. Si au lieu de cela nous avons

# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

donne

enter image description here

Maintenant, la taille apparente des marqueurs augmente approximativement linéairement de manière intuitive.

Quant à la signification exacte de ce qu'est un "point", il est assez arbitraire de tracer des graphiques, vous pouvez simplement redimensionner toutes vos tailles jusqu'à ce qu'elles paraissent raisonnables.

J'espère que cela t'aides!

Edit: (En réponse au commentaire de @Emma)

C'est probablement une formulation déroutante de ma part. La question portait sur le fait de doubler la largeur d'un cercle, de sorte que dans la première image de chaque cercle (de gauche à droite), sa largeur est le double de la précédente. Il s'agit donc d'une exponentielle avec la base 4. De la même manière, le deuxième exemple chaque cercle a une aire double le dernier qui donne une exponentielle en base 2.

Cependant, c’est le deuxième exemple (où nous mesurons une zone) où une zone doublée semble rendre le cercle deux fois plus grand à l’œil. Ainsi, si nous voulons qu'un cercle apparaisse avec un facteur de n plus grand, nous augmenterons la surface d'un facteur n et non du rayon, de sorte que la taille apparente soit proportionnelle à la surface.

325
Dan

Etant donné que d'autres réponses prétendent que s désigne l'aire du marqueur, j'ajoute cette réponse pour indiquer clairement que ce n'est pas nécessairement le cas.

Taille en points ^ 2

L'argument s dans plt.scatter désigne le markersize**2. Comme le dit la documentation

s: scalaire ou matriciel, forme (n,), facultatif
taille en points ^ 2. La valeur par défaut est rcParams ['lines.markersize'] ** 2.

Cela peut être pris à la lettre. Pour obtenir un marqueur dont les points x sont grands, vous devez relier ce nombre et le donner à l'argument s.

Ainsi, la relation entre la taille du marqueur d'un tracé de ligne et l'argument de la taille de dispersion est le carré. Afin de produire un marqueur de dispersion de la même taille qu'un marqueur de tracé de taille 10, appelez donc scatter( .., s=100).

enter image description here

import matplotlib.pyplot as plt

fig,ax = plt.subplots()

ax.plot([0],[0], marker="o",  markersize=10)
ax.plot([0.07,0.93],[0,0],    linewidth=10)
ax.scatter([1],[0],           s=100)

ax.plot([0],[1], marker="o",  markersize=22)
ax.plot([0.14,0.86],[1,1],    linewidth=22)
ax.scatter([1],[1],           s=22**2)

plt.show()

Connexion à "zone"

Alors, pourquoi les autres réponses et même la documentation parlent-elles de "zone" en ce qui concerne le paramètre s?

Bien sûr, les unités de points ** 2 sont des unités de surface.

  • Dans le cas particulier d'un marqueur carré, marker="s", l'aire du marqueur est en effet directement la valeur du paramètre s.
  • Pour un cercle, l'aire du cercle est area = pi/4*s.
  • Pour d'autres marqueurs, il peut ne pas même y avoir de relation évidente avec la zone du marqueur.

enter image description here

Dans tous les cas, l'aire du marqueur est proportionnelle au paramètre s. C'est la motivation pour l'appeler "zone" même si dans la plupart des cas ce n'est pas vraiment.

Spécifier la taille des marqueurs de dispersion en termes de quantité proportionnelle à l'aire du marqueur est tout à fait logique car c'est l'aire du marqueur qui est perçue lors de la comparaison de différentes zones plutôt que sa longueur ou son diamètre de côté. C'est à dire. doubler la quantité sous-jacente devrait doubler la surface du marqueur.

enter image description here

Que sont les points?

Jusqu'à présent, la réponse à la signification de la taille d'un marqueur de dispersion est donnée en unités de points. Les points sont souvent utilisés en typographie, les polices étant spécifiées en points. De plus, les largeurs de trait sont souvent spécifiées en points. La taille standard des points dans matplotlib est de 72 points par pouce (ppi) - 1 point correspond donc à 1/72 pouce.

Il peut être utile de pouvoir spécifier des tailles en pixels au lieu de points. Si le chiffre dpi est également 72, un point est un pixel. Si le chiffre dpi est différent (la valeur par défaut de matplotlib est fig.dpi=100),

1 point == fig.dpi/72. pixels

Alors que la taille en points du marqueur de dispersion aurait donc un aspect différent pour des ppps de chiffres différents, on pourrait produire un marqueur de 10 x 10 pixels ^ 2, qui aurait toujours le même nombre de pixels couverts:

enter image description hereenter image description hereenter image description here

import matplotlib.pyplot as plt

for dpi in [72,100,144]:

    fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
    ax.set_title("fig.dpi={}".format(dpi))

    ax.set_ylim(-3,3)
    ax.set_xlim(-2,2)

    ax.scatter([0],[1], s=10**2, 
               marker="s", linewidth=0, label="100 points^2")
    ax.scatter([1],[1], s=(10*72./fig.dpi)**2, 
               marker="s", linewidth=0, label="100 pixels^2")

    ax.legend(loc=8,framealpha=1, fontsize=8)

    fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")

plt.show() 

Si vous êtes intéressé par une dispersion en unités de données, cochez cette réponse .

149

Vous pouvez utiliser markersize pour spécifier la taille du cercle dans la méthode de tracé

import numpy as np
import matplotlib.pyplot as plt

x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20)  # blue circle with size 10 
plt.plot(x2, 'ro', ms=10,)  # ms is just an alias for markersize
plt.show()

De ici

enter image description here

18
zhaoqing

C'est la zone du marqueur. Je veux dire que si vous avez s1 = 1000 puis s2 = 4000, la relation entre le rayon de chaque cercle est: r_s2 = 2 * r_s1. Voir la parcelle suivante:

plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')

enter image description here

J'ai eu le même doute quand j'ai vu le message. J'ai donc fait cet exemple, puis j'ai utilisé une règle à l'écran pour mesurer les rayons.

14
Joaquin

J'ai aussi essayé d'utiliser "scatter" au départ pour cela. Après un peu de temps perdu - je me suis installé sur la solution suivante.

import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]    
output_list = []   
for point in input_list:
    output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:    
   ax.add_artist(circle)

enter image description here

Ceci est basé sur une réponse à cette question

3
Ike

Si la taille des cercles correspond au carré du paramètre dans s=parameter, attribuez une racine carrée à chaque élément ajouté à votre tableau de taille, comme ceci: s=[1, 1.414, 1.73, 2.0, 2.24] tel que lorsqu'il prend ces valeurs et les renvoie, leur augmentation de taille relative sera la racine carrée de la progression au carré, qui renvoie une progression linéaire.

Si je devais aligner chacune d'elles au fur et à mesure de la sortie du tracé: output=[1, 2, 3, 4, 5]. Essayez d’interpréter la liste: s=[numpy.sqrt(i) for i in s]

1
user34028