es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo establecer colores de fondo personalizados de los campos de un mapa de calor de seaborn? (facecolors de matplotlib collections.QuadMesh, Python)

Quiero establecer el color de fondo de algunos campos de un mapa de calor de seaborn DESPUÉS de que se haya creado (personalizando algunos colores en función de su posición).

Puedo acceder a los valores de “facecolor” a través del objeto “collections.QuadMesh” de matplotlib. Cuando modifico los valores (he probado diferentes formas), los cambios se reflejan, pero los colores de fondo que se muestran al mostrar o exportar el gráfico no cambian.

¿Qué me falta aquí?

Este es un ejemplo (no) funcional:

import numpy as np
import numpy.testing
import pandas as pd
import seaborn as sns
from matplotlib.collections import QuadMesh
import matplotlib.pyplot as plt

CUSTOM_BACKGROUND = np.array([0.35, 0.8, 0.55, 1.0])

df = pd.DataFrame(data={'col1': [1, 1], 'col2': [2,2]})
matrix_size = df.shape[0]
ax = sns.heatmap(df)
quadmesh = ax.findobj(QuadMesh)[0]
facecolors_old = quadmesh.get_facecolors()
facecolors_new = facecolors_old.copy()
facecolors_new[1] = CUSTOM_BACKGROUND

<h1>No funciona:</h1>

quadmesh.set_facecolors(facecolors_new)

quadmesh.original_facecolor = facecolors_new

facecolors_old[1] = CUSTOM_BACKGROUND

quadmesh.facecolors[1] = CUSTOM_BACKGROUND

funciona:

quadmesh.set_facecolors('none')

pruebas pasadas:

facecolors_actual = quadmesh.get_facecolors()
numpy.testing.assert_array_equal(facecolors_new, facecolors_actual)
facecolors_actual = quadmesh.facecolors
numpy.testing.assert_array_equal(facecolors_new, facecolors_actual)

NOTA: sin embargo, al inspeccionar "quadmesh._facecolors" se muestran los valores antiguos!

muestra los colores antiguos

plt.show()

Versiones de las dependencias:

[tool.poetry.dependencies]
python = "^3.8"
pandas = "^1.2"
seaborn = "^0.11.2"

Observación:

Este enfoque solía funcionar para mí antes de actualizar las dependencias. He adaptado parte del código de aquí para dibujar matrices de confusión personalizadas utilizando el mismo enfoque: pretty-print-confusion-matrix

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que los cambios realizados en los colores de fondo del objeto QuadMesh no se están reflejando en la salida porque la función sns.heatmap() crea una copia de los datos antes de trazarlos. Por lo tanto, modificar el objeto QuadMesh después de haber sido trazado no tiene efecto en los datos originales utilizados para crear el mapa de calor.

    Una forma de lograr el resultado deseado es crear un nuevo DataFrame con los valores modificados y trazar un nuevo mapa de calor con la misma configuración que el original, excepto por los colores de fondo modificados. Por ejemplo:

    # crear un nuevo DataFrame con los valores modificados
    df_mod = df.copy()
    df_mod.iloc[1, 1] = np.nan  # establecer un color personalizado para la celda (1,1)
    # crear un nuevo mapa de calor con los colores de fondo modificados
    ax_mod = sns.heatmap(df_mod, cmap='coolwarm', annot=True,
                         fmt='d', cbar_kws={'label': 'Valor'},
                         mask=df_mod.isna(),  # ocultar los valores NaN
                         square=True)
    # obtener el objeto QuadMesh del nuevo mapa de calor
    quadmesh_mod = ax_mod.findobj(QuadMesh)[0]
    # modificar el color de fondo de la celda personalizada
    quadmesh_mod.get_facecolors()[2] = COLOR_DE_FONDO_PERSONALIZADO
    plt.show()  # mostrar el mapa de calor modificado
    

    Aquí, creamos un nuevo DataFrame df_mod con los mismos valores que df, pero modificamos el valor en la posición (1,1) para tener un color de fondo personalizado. Luego, utilizamos la misma configuración que el mapa de calor original para crear un nuevo mapa de calor ax_mod, pero con el color de fondo modificado. También utilizamos el parámetro mask para ocultar la celda modificada, ya que ahora contiene un valor NaN.

    Finalmente, obtenemos el objeto QuadMesh del nuevo mapa de calor y modificamos su color de fondo para reflejar el color de fondo personalizado. Luego podemos mostrar el mapa de calor modificado usando plt.show().

Comments are closed.