tamaño del marcador del diagrama de dispersión de pyplot
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 s
número.
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 s
en 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
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
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 n
más grande, aumentaríamos el área en un factor, n
no 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:
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()
Debido a que otras respuestas aquí afirman que s
denota el área del marcador, agrego esta respuesta para aclarar que este no es necesariamente el caso.
Tamaño en puntos^2
El argumento s
en plt.scatter
denota 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 s
argumento.
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)
.
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 s
pará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 dels
pará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.
Sin embargo, en todos los casos el área del marcador es proporcional al s
pará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.
¿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:
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 .
Es el área del marcador. Quiero decir, si tienes s1 = 1000
y 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')
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.
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í
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)
Esto se basa en una respuesta a esta pregunta.
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]