Mapear valores a colores en matplotlib

Tengo una lista de números de la siguiente manera:

lst = [1.9378076554115014, 1.2084586588892861, 1.2133096565896173, 1.2427632053442292, 1.1809971732733273, 0.91960143581348919, 1.1106310149587162, 1.1106310149587162, 1.1527004351293346, 0.87318084435885079, 1.1666132876686799, 1.1666132876686799] 

Quiero convertir estos números a colores para su visualización. Quiero una escala de grises, pero cuando uso estos números como están, me da un error:

 ValueError: to_rgba: Invalid rgba arg "1.35252299785" to_rgb: Invalid rgb arg "1.35252299785" gray (string) must be in range 0-1 

… lo que entiendo se debe a que excede de 1.

A continuación, intenté dividir los elementos en la lista con el número más alto en la lista para dar valores menores a 1. Pero esto da una escala de color muy estrecha sin apenas diferencia entre los valores.

¿Hay alguna forma en la que pueda dar un rango mínimo y máximo de colores y convertir estos valores a colores? Estoy usando matplotlib.

El módulo matplotlib.colors es lo que está buscando. Esto proporciona una serie de clases para asignar desde valores a valores de mapa de colores.

 import matplotlib import matplotlib.cm as cm lst = [1.9378076554115014, 1.2084586588892861, 1.2133096565896173, 1.2427632053442292, 1.1809971732733273, 0.91960143581348919, 1.1106310149587162, 1.1106310149587162, 1.1527004351293346, 0.87318084435885079, 1.1666132876686799, 1.1666132876686799] minima = min(lst) maxima = max(lst) norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True) mapper = cm.ScalarMappable(norm=norm, cmap=cm.Greys_r) for v in lst: print(mapper.to_rgba(v)) 

El enfoque general es encontrar los minima y maxima en sus datos. Utilícelos para crear una instancia Normalize (otras clases de normalización están disponibles, por ejemplo, escala de registro). A continuación, creará un ScalarMappable utilizando la instancia Normalize y su mapa de ScalarMappable elegido. Luego puede usar mapper.to_rgba(v) para asignar desde un valor de entrada v , a través de su escala normalizada, a un color objective.

 for v in sorted(lst): print("%.4f: %.4f" % (v, mapper.to_rgba(v)[0]) ) 

Produce la salida:

 0.8732: 0.0000 0.9196: 0.0501 1.1106: 0.2842 1.1106: 0.2842 1.1527: 0.3348 1.1666: 0.3469 1.1666: 0.3469 1.1810: 0.3632 1.2085: 0.3875 1.2133: 0.3916 1.2428: 0.4200 1.9378: 1.0000 

La documentación del módulo matplotlib.colors tiene más información si es necesario.

Los mapas de colores son poderosos, pero (a) a menudo puedes hacer algo más simple y (b) porque son poderosos, a veces hacen más de lo que esperaba. Extendiendo el ejemplo de mfitzp:

 import matplotlib import matplotlib.cm as cm lst = [1.9378076554115014, 1.2084586588892861, 1.2133096565896173, 1.2427632053442292, 1.1809971732733273, 0.91960143581348919, 1.1106310149587162, 1.1106310149587162, 1.1527004351293346, 0.87318084435885079, 1.1666132876686799, 1.1666132876686799] minima = min(lst) maxima = max(lst) norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True) mapper = cm.ScalarMappable(norm=norm, cmap=cm.Greys) for v in lst: print(mapper.to_rgba(v)) # really simple grayscale answer algebra_list = [(x-minima)/(maxima-minima) for x in lst] # let's compare the mapper and the algebra mapper_list = [mapper.to_rgba(x)[0] for x in lst] matplotlib.pyplot.plot(lst, mapper_list, color='red', label='ScalarMappable') matplotlib.pyplot.plot(lst, algebra_list, color='blue', label='Algebra') # I did not expect them to go in opposite directions. Also, interesting how # Greys uses wider spacing for darker colors. # You could use Greys_r (reversed) # Also, you can do the colormapping in a call to scatter (for instance) # it will do the normalizing itself matplotlib.pyplot.scatter(lst, lst, c=lst, cmap=cm.Greys, label='Default norm, Greys') matplotlib.pyplot.scatter(lst, [x-0.25 for x in lst], marker='s', c=lst, cmap=cm.Greys_r, label='Reversed Greys, default norm') matplotlib.pyplot.legend(bbox_to_anchor=(0.5, 1.05)) 

valores de colores normados