Yotam
Supongamos que tengo tres conjuntos de datos:
X = [1,2,3,4]
Y1 = [4,8,12,16]
Y2 = [1,4,9,16]
Puedo diagrama de dispersión esto:
from matplotlib import pyplot as plt
plt.scatter(X,Y1,color="red")
plt.scatter(X,Y2,color="blue")
plt.show()
¿Cómo puedo hacer esto con 10 juegos?
Busqué esto y pude encontrar alguna referencia a lo que estoy preguntando.
Editar: aclarar (con suerte) mi pregunta
Si llamo a scatter varias veces, solo puedo establecer el mismo color en cada scatter. Además, sé que puedo configurar una matriz de colores manualmente, pero estoy seguro de que hay una mejor manera de hacerlo. Entonces, mi pregunta es: “¿Cómo puedo hacer un diagrama de dispersión automático de varios conjuntos de datos, cada uno con un color diferente?
Si eso ayuda, puedo asignar fácilmente un número único a cada conjunto de datos.
DSM
No sé a qué te refieres con ‘manualmente’. Puede elegir un mapa de colores y hacer una matriz de colores con bastante facilidad:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]
colors = cm.rainbow(np.linspace(0, 1, len(ys)))
for y, c in zip(ys, colors):
plt.scatter(x, y, color=c)
O puede hacer su propio ciclador de color usando itertools.cycle
y especificando los colores que desea repetir, usando next
para conseguir el que quieres. Por ejemplo, con 3 colores:
import itertools
colors = itertools.cycle(["r", "b", "g"])
for y in ys:
plt.scatter(x, y, color=next(colors))
Ahora que lo pienso, tal vez sea más limpio no usarlo zip
con el primero tampoco:
colors = iter(cm.rainbow(np.linspace(0, 1, len(ys))))
for y in ys:
plt.scatter(x, y, color=next(colors))
-
+1. Sin embargo, un ciclo de itertools probablemente no sea una buena idea en esta situación, ya que terminaría con múltiples conjuntos de datos con el mismo color.
–David Robinson
02/09/2012 a las 14:40
-
@DavidRobinson: no si especifica los diez, aunque estoy de acuerdo en que el ciclismo anula el propósito allí… :^)
– DSM
2 de septiembre de 2012 a las 14:41
-
Precisamente, entonces no es un ciclo 🙂
–David Robinson
2 de septiembre de 2012 a las 14:42
-
@macrocosme: funciona para mí. agregando
plt.legend(['c{}'.format(i) for i in range(len(ys))], loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0., fontsize=11)
al fondo lo de arriba me da una leyenda con colores.– DSM
07/04/2013 a las 19:15
-
la solución de itertools es genial cuando quieres evitar algunos colores. En mi caso como el fondo es negro quiero evitar el negro.
– Fabricio
17 de septiembre de 2013 a las 13:06
marcos catherine blanco
La forma normal de trazar parcelas con puntos en diferentes colores en matplotlib es pasar una lista de colores como parámetro.
P.ej:
import matplotlib.pyplot
matplotlib.pyplot.scatter([1,2,3],[4,5,6],color=['red','green','blue'])
Cuando tienes una lista de listas y las quieres coloreadas por lista. Creo que la forma más elegante es la sugerida por @DSM, solo haz un ciclo haciendo múltiples llamadas para dispersar.
Pero si por alguna razón quisieras hacerlo con una sola llamada, puedes hacer una gran lista de colores, con una lista de comprensión y un poco de división de pisos:
import matplotlib
import numpy as np
X = [1,2,3,4]
Ys = np.array([[4,8,12,16],
[1,4,9,16],
[17, 10, 13, 18],
[9, 10, 18, 11],
[4, 15, 17, 6],
[7, 10, 8, 7],
[9, 0, 10, 11],
[14, 1, 15, 5],
[8, 15, 9, 14],
[20, 7, 1, 5]])
nCols = len(X)
nRows = Ys.shape[0]
colors = matplotlib.cm.rainbow(np.linspace(0, 1, len(Ys)))
cs = [colors[i//len(X)] for i in range(len(Ys)*len(X))] #could be done with numpy's repmat
Xs=X*nRows #use list multiplication for repetition
matplotlib.pyplot.scatter(Xs,Ys.flatten(),color=cs)
cs = [array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.5, 0. , 1. , 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
array([ 0.28039216, 0.33815827, 0.98516223, 1. ]),
...
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00]),
array([ 1.00000000e+00, 1.22464680e-16, 6.12323400e-17,
1.00000000e+00])]
-
Esto es realmente genial para un gráfico de dispersión en el que tengo datos diarios de qué tan grande es un archivo de texto, y si agregué menos de, digamos, 200 bytes, hago un punto rojo, pero de lo contrario es verde.
– aschultz
14 de julio de 2021 a las 16:07
GM
Una solución fácil
Si solo tiene un tipo de colecciones (por ejemplo, dispersión sin barras de error), también puede cambiar los colores después de haberlos trazado, esto a veces es más fácil de realizar.
import matplotlib.pyplot as plt
from random import randint
import numpy as np
#Let's generate some random X, Y data X = [ [frst group],[second group] ...]
X = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
Y = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
labels = range(1,len(X)+1)
fig = plt.figure()
ax = fig.add_subplot(111)
for x,y,lab in zip(X,Y,labels):
ax.scatter(x,y,label=lab)
La única pieza de código que necesita:
#Now this is actually the code that you need, an easy fix your colors just cut and paste not you need ax.
colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired
colorst = [colormap(i) for i in np.linspace(0, 0.9,len(ax.collections))]
for t,j1 in enumerate(ax.collections):
j1.set_color(colorst
ax.legend(fontsize="small")
La salida le brinda diferentes colores incluso cuando tiene muchos diagramas de dispersión diferentes en el mismo subparcela.
-
eso es genial, pero ¿cómo agregarías, por ejemplo, barras de error con el mismo color con esta función? @GM
– PEBKAC
20 de julio de 2018 a las 12:48
-
Hola @PEBKAC, gracias por señalarlo, me esforcé mucho esta tarde para que funcione también en ese caso, pero no pude encontrar ninguna solución, así que edité la pregunta y advertí a los otros usuarios. ¡Gracias!
– GM
20/07/2018 a las 15:00
-
Hola @GM, lo siento, publiqué algunos comentarios antes de finalizar la solución, que se describe aquí: stackoverflow.com/q/51444364/7541421
– PEBKAC
20/07/2018 a las 17:30
-
Usé otro método para asignar los colores de cada serie en un diagrama de dispersión. Ahora funciona, desafortunadamente no pude continuar con su solución elegante cuando se trataba de barras de error, ¡aún estoy muy agradecido por su publicación súper útil! ¡Salud!
– PEBKAC
20 de julio de 2018 a las 17:31
Ofir Carmi
Siempre puedes usar el plot()
funcionar así:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]
plt.figure()
for y in ys:
plt.plot(x, y, 'o')
plt.show()
Esta pregunta es un poco complicada antes de enero de 2013 y matplotlib 1.3.1 (agosto de 2013), que es la versión estable más antigua que puede encontrar en el sitio web de matpplotlib. Pero después de eso es bastante trivial.
Porque la versión actual de matplotlib.pylab.scatter
asignación de soporte: matriz de cadena de nombre de color, matriz de número flotante con mapa de color, matriz de RGB o RGBA.
esta respuesta está dedicada a la pasión infinita de @Oxinabox por corregir la versión 2013 de mí mismo en 2015.
tiene dos opciones de usar el comando de dispersión con varios colores en una sola llamada.
-
como
pylab.scatter
soporte de comando use matriz RGBA para hacer cualquier color que desee; -
a principios de 2013, no hay forma de hacerlo, ya que el comando solo admite un solo color para toda la colección de puntos de dispersión. Cuando estaba haciendo mi proyecto de 10000 líneas, descubrí una solución general para evitarlo. entonces es muy hortera, pero puedo hacerlo en cualquier forma, color, tamaño y transparente. este truco también podría aplicarse para dibujar una colección de rutas, una colección de líneas….
el código también está inspirado en el código fuente de pyplot.scatter
solo dupliqué lo que hace la dispersión sin activarlo para dibujar.
El comando pyplot.scatter
devolver un PatchCollection
Objeto, en el archivo “matplotlib/collections.py” una variable privada _facecolors
en Collection
clase y un método set_facecolors
.
así que cada vez que tenga puntos de dispersión para dibujar, puede hacer esto:
# rgbaArr is a N*4 array of float numbers you know what I mean
# X is a N*2 array of coordinates
# axx is the axes object that current draw, you get it from
# axx = fig.gca()
# also import these, to recreate the within env of scatter command
import matplotlib.markers as mmarkers
import matplotlib.transforms as mtransforms
from matplotlib.collections import PatchCollection
import matplotlib.markers as mmarkers
import matplotlib.patches as mpatches
# define this function
# m is a string of scatter marker, it could be 'o', 's' etc..
# s is the size of the point, use 1.0
# dpi, get it from axx.figure.dpi
def addPatch_point(m, s, dpi):
marker_obj = mmarkers.MarkerStyle(m)
path = marker_obj.get_path()
trans = mtransforms.Affine2D().scale(np.sqrt(s*5)*dpi/72.0)
ptch = mpatches.PathPatch(path, fill = True, transform = trans)
return ptch
patches = []
# markerArr is an array of maker string, ['o', 's'. 'o'...]
# sizeArr is an array of size float, [1.0, 1.0. 0.5...]
for m, s in zip(markerArr, sizeArr):
patches.append(addPatch_point(m, s, axx.figure.dpi))
pclt = PatchCollection(
patches,
offsets = zip(X[:,0], X[:,1]),
transOffset = axx.transData)
pclt.set_transform(mtransforms.IdentityTransform())
pclt.set_edgecolors('none') # it's up to you
pclt._facecolors = rgbaArr
# in the end, when you decide to draw
axx.add_collection(pclt)
# and call axx's parent to draw_idle()
-
por lo que es un poco complicado de leer y en 2013 usé python durante 1 año. Entonces, ¿por qué la gente querría saber cómo hacerlo? después de hacerlo funcionar, nunca me molesto en mirarlo de nuevo. mi proyecto era dibujar mucha visualización, con el código anterior, el flujo de trabajo se simplificó.
– Hualín
18 de septiembre de 2015 a las 12:39
MDM
Una solución MUCHO más rápida para grandes conjuntos de datos y un número limitado de colores es el uso de Pandas y la función groupby:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
# a generic set of data with associated colors
nsamples=1000
x=np.random.uniform(0,10,nsamples)
y=np.random.uniform(0,10,nsamples)
colors={0:'r',1:'g',2:'b',3:'k'}
c=[colors[i] for i in np.round(np.random.uniform(0,3,nsamples),0)]
plt.close('all')
# "Fast" Scatter plotting
starttime=time.time()
# 1) make a dataframe
df=pd.DataFrame()
df['x']=x
df['y']=y
df['c']=c
plt.figure()
# 2) group the dataframe by color and loop
for g,b in df.groupby(by='c'):
plt.scatter(b['x'],b['y'],color=g)
print('Fast execution time:', time.time()-starttime)
# "Slow" Scatter plotting
starttime=time.time()
plt.figure()
# 2) group the dataframe by color and loop
for i in range(len(x)):
plt.scatter(x[i],y[i],color=c[i])
print('Slow execution time:', time.time()-starttime)
plt.show()
-
por lo que es un poco complicado de leer y en 2013 usé python durante 1 año. Entonces, ¿por qué la gente querría saber cómo hacerlo? después de hacerlo funcionar, nunca me molesto en mirarlo de nuevo. mi proyecto era dibujar mucha visualización, con el código anterior, el flujo de trabajo se simplificó.
– Hualín
18 de septiembre de 2015 a las 12:39
Angustia
Esto funciona para mí:
para cada serie, use un generador de color rgb aleatorio
c = color[np.random.random_sample(), np.random.random_sample(), np.random.random_sample()]
-
No sé cuál es su variable de color, pero usando su enfoque es posible hacer algo como:
plt.scatter(your values to the graph, color= (np.random.random_sample(), np.random.random_sample(), np.random.random_sample()) )
. Mencionó un generador RGB y declaró una lista RGB, los generadores se declaran entre ‘()’– Joel Carneiro
14 de enero de 2019 a las 15:52
¿Cuál es la pregunta aquí? El color también puede ser una matriz, pero ¿qué no se puede resolver simplemente llamando a la dispersión varias veces?
– seberg
2 de septiembre de 2012 a las 14:22
Si llamo a scatter varias veces, obtengo los mismos colores. Actualizaré mi pregunta.
– Yotam
2 de septiembre de 2012 a las 14:24