Heatmap

Python
code
Visualization
Author

Marco Aguirre

Published

September 29, 2025

Un heatmap es una representación gráfica de datos en la que los valores contenidos en una matriz se muestran mediante colores. Es como observar una tabla de datos “desde arriba”, donde cada celda refleja la magnitud de un valor en función de su tonalidad.

Este tipo de gráfico es especialmente útil para obtener una visión general de un conjunto numérico, más que para extraer valores específicos.

Heatmaps se utilizan con frecuencia para mostrar los resultados de un análisis de clustering jerárquico, acompañados de dendrogramas que agrupan filas y columnas según sus similitudes. Esto permite identificar patrones comunes, como países con características demográficas parecidas o variables fuertemente correlacionadas.

Variaciones

  • Mostrar el resultado de un clustering y comparar con expectativas (ejemplo: agrupaciones por continente).
  • Incluir los valores exactos en cada celda para facilitar la lectura numérica.
  • Usarlos en series temporales donde existen patrones regulares.
  • Aplicarlos a matrices de adyacencia para redes o grafos.

Errores habituales

  • No normalizar los datos antes de graficar.
  • No reordenar filas y columnas según los resultados de un clustering, lo que dificulta ver patrones.
  • Elegir una paleta de colores inadecuada, que confunda en lugar de resaltar diferencias.

Dataset: Precios Agroindustria de Cacao (2012 - 2025)

Archivo: MAG_PreciosAgroindustriaCacao_2025Junio.csv
Fuente: Ministerio de Agricultura y Ganadería (MAG), Ecuador
Última actualización: Junio 2025

import pandas as pd
df = pd.read_csv("mag_preciosagroindustriacacao_2025junio.csv", sep=";")
print(df.head())
print(df.info())
   PACC_ANIO PACC_MES DPA_PROVINCIA DPA_CANTON        PACC_PRODUCTO  \
0       2012    Enero        El Oro  Arenillas  Cacao seco mezclado   
1       2012    Enero        El Oro  Arenillas  Cacao seco mezclado   
2       2012    Enero        El Oro   El Guabo  Cacao seco mezclado   
3       2012    Enero        El Oro   El Guabo  Cacao seco mezclado   
4       2012    Enero        El Oro    Machala  Cacao seco mezclado   

          PACC_PRESENTACION PACC_TIPO  PACC_PRECIO_USD  PACC_USD_KG  
0  Quintal de 100,00 libras    Compra            71.41         1.57  
1  Quintal de 100,00 libras     Venta            74.06         1.63  
2  Quintal de 100,00 libras    Compra            73.75         1.63  
3  Quintal de 100,00 libras     Venta            84.00         1.85  
4  Quintal de 100,00 libras    Compra            75.00         1.65  
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 26246 entries, 0 to 26245
Data columns (total 9 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   PACC_ANIO          26246 non-null  int64  
 1   PACC_MES           26246 non-null  object 
 2   DPA_PROVINCIA      26246 non-null  object 
 3   DPA_CANTON         26246 non-null  object 
 4   PACC_PRODUCTO      26246 non-null  object 
 5   PACC_PRESENTACION  26246 non-null  object 
 6   PACC_TIPO          26246 non-null  object 
 7   PACC_PRECIO_USD    26246 non-null  float64
 8   PACC_USD_KG        26246 non-null  float64
dtypes: float64(2), int64(1), object(6)
memory usage: 1.8+ MB
None

Iteración 1

import plotly.express as px
import plotly.io as pio
pio.renderers.default = "notebook"

# Agrupar: precio promedio por año y cantón
df_pivot = (
    df.groupby(["PACC_ANIO", "DPA_CANTON"])["PACC_PRECIO_USD"]
      .mean()
      .reset_index()
      .pivot(index="DPA_CANTON", columns="PACC_ANIO", values="PACC_PRECIO_USD")
)

# Convertir el pivot a formato largo (para Plotly)
df_long = df_pivot.reset_index().melt(id_vars="DPA_CANTON", var_name="PACC_ANIO", value_name="PACC_PRECIO_USD")

# Crear heatmap
fig = px.imshow(
    df_pivot.values,
    labels=dict(x="Año", y="Cantón", color="Precio USD"),
    x=df_pivot.columns,
    y=df_pivot.index,
    color_continuous_scale="Viridis"
)

# Ajustes de diseño
fig.update_layout(
    title="Precio promedio en USD por año y cantón",
    xaxis=dict(side="top"),  # años arriba
    font=dict(family="Arial", size=12),
    plot_bgcolor="white",
    margin=dict(l=80, r=40, t=80, b=40)
)

fig.show()

Iteración 2

  • Cambio de nulos por 0
  • Presenta datos en cajas

# Reemplazar NaN por 0
df_pivot = df_pivot.fillna(0)

# Crear heatmap
fig = px.imshow(
    df_pivot.values,
    labels=dict(x="Año", y="Cantón", color="Precio USD"),
    x=df_pivot.columns,
    y=df_pivot.index,
    color_continuous_scale="Viridis",
    text_auto=".2f"   # mostrar valores dentro de cada celda con 2 decimales
)

# Ajustes de diseño
fig.update_layout(
    title="Precio promedio en USD por año y cantón",
    xaxis=dict(side="top"),
    font=dict(family="Arial", size=12),
    plot_bgcolor="white",
    margin=dict(l=80, r=40, t=80, b=40)
)

fig.show()

Iteración 3

  • Borde cajas Blanco
  • Eliminación de eje y eje x
import pandas as pd
import plotly.express as px

# Agrupar: precio promedio por año y cantón
df_pivot = (
    df.groupby(["PACC_ANIO", "DPA_CANTON"])["PACC_PRECIO_USD"]
      .mean()
      .reset_index()
      .pivot(index="DPA_CANTON", columns="PACC_ANIO", values="PACC_PRECIO_USD")
)

# Reemplazar NaN por 0
df_pivot = df_pivot.fillna(0)

# Crear heatmap
fig = px.imshow(
    df_pivot.values,
    labels=dict(x="Año", y="Cantón", color="Precio USD"),
    x=df_pivot.columns,
    y=df_pivot.index,
    color_continuous_scale="Viridis"
)

# Borde blanco entre celdas
fig.update_traces(
    xgap=2,  # separación entre columnas
    ygap=2   # separación entre filas
)

# Ajustes de diseño
fig.update_layout(
    title="Precio promedio en USD por año y cantón",
    xaxis=dict(side="top", title=""),   # Quitar nombre eje X
    yaxis=dict(title=""),               # Quitar nombre eje Y
    font=dict(family="Arial", size=12),
    plot_bgcolor="white",
    margin=dict(l=80, r=40, t=80, b=40),
    coloraxis_showscale=False           # Quitar barra de color
)

fig.show()

Iteración 3

  • Ordenamiento

# Ordenar cantones por promedio total (de mayor a menor)
df_pivot = df_pivot.loc[df_pivot.mean(axis=1).sort_values(ascending=False).index]

# Crear heatmap
fig = px.imshow(
    df_pivot.values,
    labels=dict(x="Año", y="Cantón", color="Precio USD"),
    x=df_pivot.columns,
    y=df_pivot.index,
    color_continuous_scale="Viridis"
)

# Ajustes de diseño
fig.update_layout(
    title="Precio promedio en USD por año y cantón",

    xaxis=dict(side="top", title=""),
    yaxis=dict(title=""),
    font=dict(family="Arial", size=12),
    plot_bgcolor="white",
    margin=dict(l=80, r=40, t=80, b=40),
    coloraxis_showscale=False
)

fig.show()