498 votes

pyplot scatter plot taille des marqueurs

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 : la 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 cela signifie ? Est-ce que s=100 moyenne 10 pixel x 10 pixel ?

En gros, j'essaie de faire des diagrammes de dispersion avec différentes tailles de marqueurs, et je veux savoir ce que fait l'option s le nombre signifie.

1 votes

Je suis presque sûr que les points sont les mêmes unités que celles utilisées pour les polices de caractères.

2 votes

@tcaswell, vous voulez dire s=20 signifie que la taille du marqueur est égale à celle d'un fontsize=20 lettre ?

0 votes

Non, l'aire sera de 20 points^2, a fontsize=20 La lettre fait 20 points de haut (ou le caractère de référence de la police fait 20 points de haut).

531voto

Dan Points 2233

Cette façon de définir la taille peut être quelque peu déroutante, mais vous spécifiez en fait la taille de l'unité de mesure. zone du marqueur. En d'autres termes, pour doubler la largeur (ou la hauteur) du marqueur, vous devez augmenter la taille de l'indicateur. s par un facteur de 4. [parce que A = W H => (2W) (2H)=4A]

Il y a toutefois une raison pour laquelle la taille des marqueurs est définie de cette manière. En raison de la mise à l'échelle de la surface en tant que carré de la largeur, le doublement de la largeur semble en fait augmenter la taille par un facteur supérieur à 2 (en fait, il l'augmente par un facteur de 4). Pour s'en convaincre, il suffit de considérer les deux exemples suivants et les résultats 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 à la place 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 de façon linéaire, de manière intuitive.

Quant à la signification exacte de ce qu'est un "point", elle est assez arbitraire pour les tracés, vous pouvez simplement mettre à l'échelle toutes vos tailles par une constante jusqu'à ce qu'elles aient l'air raisonnables.

J'espère que cela vous aidera !

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

C'est probablement une formulation confuse de ma part. La question portait sur le doublement de la largeur d'un cercle. Ainsi, dans le premier exemple, la largeur de chaque cercle (en allant de gauche à droite) est le double de celle du cercle précédent, ce qui correspond à une exponentielle de base 4. De même, dans le deuxième exemple, chaque cercle a zone double le dernier qui donne une exponentielle en base 2.

Cependant, c'est dans le deuxième exemple (où nous mettons la surface à l'échelle) que le fait de doubler la surface semble rendre le cercle deux fois plus grand à l'œil. Ainsi, si nous voulons qu'un cercle apparaisse d'un facteur de n plus grande, nous augmenterions la surface d'un facteur n pas le rayon, de sorte que la taille apparente s'échelonne linéairement avec la surface.

Modifier pour visualiser le commentaire de @TomaszGandor :

Voici à quoi cela ressemble pour différentes fonctions de la taille du marqueur :

Exponential, Square, or Linear size

x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()

2 votes

Je ne comprends probablement pas bien ce que vous voulez dire, mais dans votre deuxième exemple, vous augmentez s de manière exponentielle (s=[20, 40, 80, 160, 320, 640]) et vous dites que cela nous donne une belle augmentation linéaire de la taille. Ne serait-il pas plus logique d'augmenter la taille de façon linéaire (ex. s=[20, 40, 60, 80, 100, 120]) pour obtenir un résultat linéaire ?

0 votes

Votre intuition est juste, c'est une mauvaise formulation de ma part (ou un mauvais choix de l'échelle de l'axe des x). J'ai expliqué un peu plus dans une édition parce que c'était trop long pour un commentaire.

1 votes

Est-il possible de changer s en fonction de la taille de la fenêtre de la figure ? Je veux dire, si nous maximisons la fenêtre de la figure, j'aimerais avoir des marques de plus grande taille.

313voto

Parce que d'autres réponses ici prétendent que s désigne la zone du marqueur, j'ajoute cette réponse pour préciser que ce n'est pas nécessairement le cas.

Taille en points^2

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

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

Cela peut être pris au pied de la lettre. Pour obtenir un marqueur de x points, il faut élever ce nombre au carré et le donner au s argument.

Ainsi, la relation entre la taille du marqueur d'un graphique linéaire et l'argument de la taille du nuage de points est le carré. Pour produire un marqueur de dispersion de la même taille qu'un marqueur de tracé de taille 10 points, il faut donc appeler 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()

Raccordement à la "zone

Alors pourquoi les autres réponses et même la documentation parlent de "zone" lorsqu'il s'agit de la s paramètre ?

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

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

enter image description here

Dans tous les cas, cependant, la surface du marqueur est proportionnelle à la taille de l'échantillon. s paramètre . C'est la raison pour laquelle on l'appelle "zone", même si dans la plupart des cas, elle ne l'est pas vraiment.

Spécifier la taille des marqueurs de diffusion en termes d'une quantité proportionnelle à la surface du marqueur est donc logique dans la mesure où c'est la surface du marqueur qui est perçue lors de la comparaison de différents patchs plutôt que sa longueur ou son diamètre. En d'autres termes, le fait de 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 question de savoir ce que signifie la taille d'un marqueur de dispersion est donnée en unités de points. Les points sont souvent utilisés en typographie, où les polices de caractères sont spécifiées en points. De même, la largeur des lignes est souvent spécifiée en points. La taille standard des points dans matplotlib est de 72 points par pouce (ppi) - 1 point correspond donc à 1/72 pouces.

Il pourrait être utile de pouvoir spécifier les tailles en pixels plutôt qu'en points. Si le dpi de la figure est également de 72, un point correspond à un pixel. Si le dpi de la figure est différent (le défaut de matplotlib est fig.dpi=100 ),

1 point == fig.dpi/72. pixels

Alors que la taille en points du marqueur de diffusion serait donc différente pour différentes dpi de chiffres, on pourrait produire un marqueur de 10 par 10 pixels^2, qui aurait toujours le même nombre de pixels couverts :

enter image description here enter image description here enter 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 dans les unités de données, vérifiez les points suivants cette réponse .

0 votes

Je me demande comment calculer le paramètre s à donner à la dispersion pour obtenir un cercle qui couvre un diamètre de, disons, 0,1 dans les coordonnées réelles du tracé (de manière à combler l'écart entre, disons, 0,4 et 0,5 sur un tracé de (0,0) à (1,1)) ?

0 votes

@AnatolyAlekseev Cette réponse devrait être donnée par ce question.

0 votes

@ImportanceOfBeingErnest pourriez-vous nous expliquer comment obtenir le rayon d'un nuage de points en fonction de l'indice de référence ? s paramètre passé ? Je pensais que c'était np.sqrt(s)/2 . stackoverflow.com/q/64399664/9900084

33voto

Joaquin Points 381

C'est le zone du marqueur. Je veux dire que si vous avez s1 = 1000 y luego s2 = 4000 la relation entre les rayons de chaque cercle est la suivante : r_s2 = 2 * r_s1 . Voir le graphique suivant :

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 en voyant le post, j'ai donc fait cet exemple puis j'ai utilisé une règle à l'écran pour mesurer les rayons.

1 votes

C'est la réponse la plus propre et la moins grasse. Merci

0 votes

+1, et en effet s est un raccourci para markersize comme c est un raccourci pour color . Référence . Si la documentation de matplotlib pouvait être aussi simple que cette réponse au lieu d'ajouter du bruit à chaque ligne...

33voto

zhaoqing Points 199

Vous pouvez utiliser Taille des marqueurs 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

2 votes

La question portait sur le nuage de points, et dans matplotlib les deux fonctions de traçage ont des paramètres différents ( Taille des marqueurs para intrigue et s para se disperser ). Cette réponse ne s'applique donc pas.

3 votes

@Dom J'ai upvoted, parce que cette question apparaît comme le premier résultat dans google même quand je cherche "pyplot plot marker size", donc cette réponse aide.

0 votes

Je sais que la méthode plot et la méthode scatter sont différentes dans plt mais elles peuvent toutes deux réaliser le 'scatter plot' et ajuster la taille des marqueurs, donc cette réponse est juste un autre contournement si vous utilisez la méthode plot @Dom

8voto

Ike Points 669

J'ai également essayé d'utiliser initialement "scatter" à cette fin. Après avoir perdu pas mal de temps, j'ai trouvé 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

1 votes

Très utile. Mais pourquoi utiliser deux boucles ?

1 votes

@grabantot aucune raison, je n'y ai pas trop pensé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X