tamaño del marcador del diagrama de dispersión de pyplot

Resuelto LWZ asked hace 11 años • 7 respuestas

En el documento de pyplot para el diagrama de dispersión:

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)

El tamaño del marcador

s: tamaño en puntos^2. Es un escalar o una matriz de la misma longitud que xey.

¿ Qué tipo de unidad es points^2? ¿Qué significa? Significa ? s=100_10 pixel x 10 pixel

Básicamente, estoy tratando de hacer diagramas de dispersión con diferentes tamaños de marcadores y quiero descubrir qué significa el snúmero.

LWZ avatar Feb 12 '13 14:02 LWZ
Aceptado

Esta puede ser una forma algo confusa de definir el tamaño, pero básicamente estás especificando el área del marcador. Esto significa que, para duplicar el ancho (o alto) del marcador, debe aumentarlo sen un factor de 4. [porque A = W H => (2W) (2H)=4A]

Sin embargo, hay una razón por la que el tamaño de los marcadores se define de esta manera. Debido a la escala del área como el cuadrado del ancho, duplicar el ancho en realidad parece aumentar el tamaño en más de un factor de 2 (de hecho, lo aumenta en un factor de 4). Para ver esto, considere los siguientes dos ejemplos y el resultado que producen.

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

da

ingrese la descripción de la imagen aquí

Observe cómo el tamaño aumenta muy rápidamente. Si en cambio tenemos

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

da

ingrese la descripción de la imagen aquí

Ahora el tamaño aparente de los marcadores aumenta aproximadamente linealmente de forma intuitiva.

En cuanto al significado exacto de lo que es un "punto", es bastante arbitrario a efectos de trazado; puede escalar todos los tamaños mediante una constante hasta que parezcan razonables.

Editar: (En respuesta al comentario de @Emma)

Probablemente sea una redacción confusa de mi parte. La pregunta era sobre duplicar el ancho de un círculo, por lo que en la primera imagen para cada círculo (a medida que nos movemos de izquierda a derecha) su ancho es el doble que el anterior, por lo que para el área es un exponencial con base 4. De manera similar, el segundo ejemplo cada círculo tiene el doble de área que el último lo que da un exponencial con base 2.

Sin embargo, en el segundo ejemplo (en el que estamos escalando el área), al duplicar el área parece que el círculo es dos veces más grande a la vista. Por lo tanto, si queremos que un círculo parezca un factor nmás grande, aumentaríamos el área en un factor, nno en el radio, de modo que el tamaño aparente aumente linealmente con el área.

Edite para visualizar el comentario de @TomaszGandor:

Así es como se ve para diferentes funciones del tamaño del marcador:

Tamaño exponencial, cuadrado o lineal

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()
Dan avatar Feb 13 '2013 18:02 Dan

Debido a que otras respuestas aquí afirman que sdenota el área del marcador, agrego esta respuesta para aclarar que este no es necesariamente el caso.

Tamaño en puntos^2

El argumento sen plt.scatterdenota el markersize**2. Como dice la documentación

s: escalar o tipo matriz, forma (n,),
tamaño opcional en puntos^2. El valor predeterminado es rcParams['lines.markersize'] ** 2.

Esto puede tomarse literalmente. Para obtener un marcador de x puntos de tamaño, es necesario elevar ese número al cuadrado y dárselo al sargumento.

Entonces, la relación entre el tamaño del marcador de un gráfico lineal y el argumento del tamaño de dispersión es el cuadrado. Para producir un marcador de dispersión del mismo tamaño que un marcador de trama de tamaño 10 puntos, entonces llamarías scatter( .., s=100).

ingrese la descripción de la imagen aquí

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

Conexión al "área"

Entonces, ¿por qué otras respuestas e incluso la documentación hablan de "área" cuando se trata del sparámetro?

Por supuesto, las unidades de puntos**2 son unidades de área.

  • Para el caso especial de un marcador cuadrado, marker="s"el área del marcador es directamente el valor del sparámetro.
  • Para un círculo, el área del círculo es area = pi/4*s.
  • Para otros marcadores puede que ni siquiera exista una relación obvia con el área del marcador.

ingrese la descripción de la imagen aquí

Sin embargo, en todos los casos el área del marcador es proporcional al sparámetro . Esta es la motivación para llamarlo "área", aunque en la mayoría de los casos no lo es realmente.

Hasta el momento, tiene sentido especificar el tamaño de los marcadores de dispersión en términos de alguna cantidad que sea proporcional al área del marcador, ya que es el área del marcador lo que se percibe al comparar diferentes parches en lugar de su longitud o diámetro lateral. Es decir, duplicar la cantidad subyacente debería duplicar el área del marcador.

ingrese la descripción de la imagen aquí

¿Qué son los puntos?

Hasta ahora, la respuesta a lo que significa el tamaño de un marcador de dispersión se da en unidades de puntos. Los puntos se utilizan a menudo en tipografía, donde las fuentes se especifican en puntos. Además, los anchos de línea suelen especificarse en puntos. El tamaño estándar de puntos en matplotlib es 72 puntos por pulgada (ppi); por lo tanto, 1 punto es 1/72 pulgadas.

Podría resultar útil poder especificar tamaños en píxeles en lugar de puntos. Si la cifra de ppp también es 72, un punto es un píxel. Si la cifra de ppp es diferente (el valor predeterminado de matplotlib es fig.dpi=100),

1 point == fig.dpi/72. pixels

Si bien el tamaño del marcador de dispersión en puntos se vería diferente para diferentes ppp de figura, se podría producir un marcador de 10 por 10 píxeles^2, que siempre tendría el mismo número de píxeles cubiertos:

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

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 está interesado en una dispersión en unidades de datos, consulte esta respuesta .

ImportanceOfBeingErnest avatar Nov 21 '2017 00:11 ImportanceOfBeingErnest

Es el área del marcador. Quiero decir, si tienes s1 = 1000y entonces s2 = 4000, la relación entre el radio de cada círculo es r_s2 = 2 * r_s1:. Vea la siguiente trama:

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

ingrese la descripción de la imagen aquí

Tuve la misma duda cuando vi el post, así que hice este ejemplo y luego usé una regla en la pantalla para medir los radios.

Joaquin avatar Apr 20 '2016 19:04 Joaquin

Puede utilizar el tamaño del marcador para especificar el tamaño del círculo en el método de trazado.

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 aquí

ingrese la descripción de la imagen aquí

zhaoqing avatar Apr 13 '2017 06:04 zhaoqing

También intenté utilizar 'scatter' inicialmente para este propósito. Después de perder bastante tiempo, me decidí por la siguiente solución.

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)

ingrese la descripción de la imagen aquí

Esto se basa en una respuesta a esta pregunta.

Ike avatar Jun 05 '2017 18:06 Ike

Si el tamaño de los círculos corresponde al cuadrado del parámetro en s=parameter, entonces asigne una raíz cuadrada a cada elemento que agregue a su matriz de tamaño, así: s=[1, 1.414, 1.73, 2.0, 2.24]de modo que cuando tome estos valores y los devuelva, su aumento de tamaño relativo será la raíz cuadrada de la progresión al cuadrado, que devuelve una progresión lineal.

Si tuviera que elevar al cuadrado cada uno a medida que se genera en la gráfica: output=[1, 2, 3, 4, 5]. Pruebe la interpretación de la lista:s=[numpy.sqrt(i) for i in s]

user34028 avatar May 26 '2015 20:05 user34028