real - Diagrama de dispersión de Python. Tamaño y estilo del marcador
matplotlib python (4)
Creo que podemos hacerlo mejor con una colección de parches. De acuerdo con los documentos:
Esto (PatchCollection) hace que sea más fácil asignar un mapa de color a una colección heterogénea de parches.
Esto también puede mejorar la velocidad de trazado , ya que PatchCollection dibujará más rápido que una gran cantidad de parches.
Supongamos que desea trazar una dispersión de círculos con un radio dado en la unidad de datos:
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
Todos los argumentos y palabras clave (excepto el marker
) de la función de scatter
funcionarían de manera similar. He escrito una gist incluye círculos , elipses y cuadrados / rectángulos . Si desea una colección de otra forma, puede modificarla usted mismo.
Si quiere trazar una barra de colores simplemente ejecute colorbar()
o pase el objeto de colección devuelto a la función de colorbar
de colorbar
.
Un ejemplo:
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)
Salida:
Tengo un conjunto de datos que quiero mostrar como un diagrama de dispersión. Quiero que cada punto se trace como un cuadrado de tamaño 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'')
El problema es que el tamaño s
que la función de dispersión es en los puntos ^ 2. Lo que me gustaría es tener cada punto representado por un cuadrado de área dx ^ 2, donde esta área está en unidades ''reales'', las unidades de la parcela. Espero que puedas entender este punto.
También tengo otra pregunta. La función de dispersión traza los marcadores con un borde negro, ¿cómo puedo soltar esta opción y no tener ningún borde?
Para que este Python 3 sea compatible, agregué el siguiente fragmento de código
try:
basestring
except NameError:
basestring = str
de
Cómo comprobar si la variable es cadena con compatibilidad python 2 y 3
Esto es necesario porque la basestring
no está disponible en Python 3. En Python 2, el propósito de la basestring
de basestring
era incluir str
y unicode
. En Python 3 no hay distinción entre str
y unicode
, y es solo str
.
Si desea marcadores que cambian de tamaño con el tamaño de la figura, puede usar parches:
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()
Tenga en cuenta que:
- Los cuadrados no están centrados en
(x,y)
. x, y son en realidad las coordenadas del cuadrado inferior izquierdo. Lo dejo de esta manera para simplificar mi código. Deberías usar(x + dx/2, y + dx/2)
. - El color se obtiene del mapa de colores caliente. Usé z ** 2 para dar colores. también debes adaptar esto a tus necesidades
Finalmente para su segunda pregunta. Puede obtener el borde de las marcas de dispersión utilizando los argumentos de palabras clave edgecolor
o edgecolors
. Estos son un argumento de color matplotlib o una secuencia de tuplas rgba, respectivamente. Si establece el parámetro en ''Ninguno'', los bordes no se dibujarán.
Traduce del sistema de coordenadas de datos de usuario al sistema de coordenadas de pantalla .
y use edgecolors = ''none'' para trazar caras sin contornos.
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'')