Revelando el Flujo: Creación de Diagramas de Sankey con Plotly en Python
Descubre cómo utilizar Plotly en Python para generar potentes diagramas de Sankey. Este tutorial te guiará paso a paso en la visualización de flujos complejos, desde la preparación de datos hasta la personalización avanzada, permitiéndote desentrañar patrones y relaciones ocultas.
Los diagramas de Sankey son una herramienta de visualización de datos extremadamente poderosa para representar flujos de información, energía, materiales o costos entre diferentes etapas o categorías. Son ideales para mostrar cómo un recurso se distribuye o se transforma a lo largo de un proceso, revelando cuellos de botella, eficiencias y pérdidas.
En este tutorial, exploraremos cómo construir estos diagramas impactantes utilizando la biblioteca Plotly en Python, conocida por sus visualizaciones interactivas y de alta calidad.
🎯 ¿Qué son los Diagramas de Sankey?
Imagina un río con sus afluentes y cómo se bifurca en diferentes arroyos. Un diagrama de Sankey es la representación visual de ese tipo de flujo. Se componen de nodos (las etapas o categorías) y enlaces (las conexiones entre nodos), donde el ancho del enlace es proporcional a la cantidad del flujo que representa.
Esto los hace excepcionalmente útiles para:
- Análisis de energía: Flujo de energía en sistemas eléctricos o industriales.
- Cadena de suministro: Movimiento de bienes desde el origen hasta el consumidor.
- Finanzas: Distribución de presupuestos o gastos.
- Ecología: Flujo de nutrientes o biomasa en ecosistemas.
- Análisis web: Rutas de usuarios a través de un sitio web.
🛠️ Requisitos Previos
Antes de sumergirnos en el código, asegúrate de tener lo siguiente:
- Python instalado (versión 3.7 o superior).
pip(el instalador de paquetes de Python).- Un entorno de desarrollo como Jupyter Notebook, VS Code o cualquier IDE de tu preferencia.
Necesitaremos instalar la biblioteca plotly. Abre tu terminal o Anaconda Prompt y ejecuta el siguiente comando:
pip install plotly pandas
pandas nos será útil para la manipulación de datos, aunque para ejemplos simples no es estrictamente necesario.
📝 Entendiendo la Estructura de Datos para Sankey
La clave para crear un diagrama de Sankey con Plotly es entender cómo debe estar estructurada la información. Plotly requiere dos componentes principales para definir el flujo:
- Nodos (
nodes): Una lista de todas las categorías o etapas que participarán en el flujo. Cada nodo debe tener una etiqueta única. - Enlaces (
links): Una lista de las conexiones entre los nodos. Cada enlace necesita unsource(origen), untarget(destino) y unvalue(el volumen del flujo).
Es importante que los source y target de los enlaces hagan referencia al índice numérico (0, 1, 2, ...) de los nodos en tu lista de nodes, no a sus nombres.
Ejemplo Simple de Estructura de Datos
Imaginemos un flujo de estudiantes que, después de terminar el bachillerato, eligen diferentes carreras y luego diferentes especializaciones.
| ID Nodo | Etiqueta del Nodo |
|---|---|
| --- | --- |
| 0 | Bachillerato |
| 1 | Ingeniería |
| --- | --- |
| 2 | Medicina |
| 3 | Artes |
| --- | --- |
| 4 | Software |
| 5 | Bioquímica |
| --- | --- |
| 6 | Diseño Gráfico |
| Fuente (ID) | Destino (ID) | Valor |
|---|---|---|
| --- | --- | --- |
| 0 | 1 | 100 |
| 0 | 2 | 70 |
| --- | --- | --- |
| 0 | 3 | 50 |
| 1 | 4 | 60 |
| --- | --- | --- |
| 1 | 5 | 40 |
| 2 | 5 | 30 |
| --- | --- | --- |
| 3 | 6 | 50 |
🚀 Primer Diagrama de Sankey Básico
Vamos a construir nuestro primer diagrama de Sankey utilizando el ejemplo de los estudiantes.
import plotly.graph_objects as go
# 1. Definir los nodos
labels = [
"Bachillerato",
"Ingeniería",
"Medicina",
"Artes",
"Software",
"Bioquímica",
"Diseño Gráfico"
]
# 2. Definir los enlaces (source, target, value)
# Recuerda que source y target son los ÍNDICES de los labels
source = [0, 0, 0, 1, 1, 2, 3]
target = [1, 2, 3, 4, 5, 5, 6]
value = [100, 70, 50, 60, 40, 30, 50]
# Crear el diagrama de Sankey
fig = go.Figure(data=[
go.Sankey(
node=dict(
pad=15, # Espacio entre nodos
thickness=20, # Grosor de los nodos
line=dict(color="black", width=0.5),
label=labels, # Etiquetas de los nodos
# color="blue" # Puedes asignar un color general a todos los nodos
),
link=dict(
source=source, # Índice de los nodos de origen
target=target, # Índice de los nodos de destino
value=value, # Valores del flujo
# color="lightgray" # Puedes asignar un color general a todos los enlaces
)
)
])
fig.update_layout(title_text="Flujo de Estudiantes por Carreras y Especializaciones", font_size=10)
fig.show()
Al ejecutar este código, verás una ventana emergente o el gráfico incrustado en tu Jupyter Notebook, mostrando un diagrama de Sankey interactivo. Pasa el ratón por encima de los nodos y enlaces para ver los detalles del flujo. ¡Es mágico!
🎨 Personalización y Estilo Avanzado
Plotly ofrece una gran cantidad de opciones para personalizar la apariencia de tus diagramas de Sankey.
Colores de Nodos y Enlaces
Puedes asignar colores específicos a cada nodo y enlace para mejorar la legibilidad y resaltar información clave.
# ... (definición de labels, source, target, value)
# Colores para los nodos (uno por cada etiqueta)
node_colors = [
"#FFD700", # Bachillerato - Oro
"#4682B4", # Ingeniería - Azul Acero
"#DC143C", # Medicina - Carmesí
"#228B22", # Artes - Verde Bosque
"#6A5ACD", # Software - Púrpura Pizarra
"#FF6347", # Bioquímica - Tomate
"#8A2BE2" # Diseño Gráfico - Azul Violeta
]
# Colores para los enlaces (uno por cada enlace)
# Puedes basar los colores en la fuente, el destino o el valor
link_colors = [
"rgba(70, 130, 180, 0.4)", # Ingeniería
"rgba(220, 20, 60, 0.4)", # Medicina
"rgba(34, 139, 34, 0.4)", # Artes
"rgba(106, 90, 205, 0.4)", # Software
"rgba(255, 99, 71, 0.4)", # Bioquímica (desde Ingeniería)
"rgba(255, 99, 71, 0.4)", # Bioquímica (desde Medicina)
"rgba(138, 43, 226, 0.4)" # Diseño Gráfico
]
fig = go.Figure(data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=labels,
color=node_colors # Asignamos los colores a los nodos
),
link=dict(
source=source,
target=target,
value=value,
color=link_colors # Asignamos los colores a los enlaces
)
)
])
fig.update_layout(title_text="Flujo de Estudiantes con Colores Personalizados", font_size=10)
fig.show()
Posición y Alineación de Nodos
Plotly permite controlar la posición horizontal (x) y vertical (y) de los nodos, así como su alineación (align). Esto es útil para organizar diagramas complejos.
x: Una lista de valores (entre 0 y 1) que representan la posición horizontal de cada nodo. 0 es la izquierda, 1 es la derecha.y: Una lista de valores (entre 0 y 1) que representan la posición vertical de cada nodo. 0 es la parte inferior, 1 es la parte superior.align: 'left', 'right', 'center'. Define la alineación de los nodos dentro de su columna vertical.
# ... (definición de labels, source, target, value, node_colors, link_colors)
# Posiciones manuales para los nodos
# Para un diagrama simple, Plotly lo organiza bien por defecto, pero puedes ajustarlo.
# Estas son solo de ejemplo para mostrar cómo se usarían.
node_x = [0.1, 0.4, 0.4, 0.4, 0.7, 0.7, 0.7]
node_y = [0.5, 0.8, 0.5, 0.2, 0.8, 0.5, 0.2]
fig = go.Figure(data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=labels,
color=node_colors,
x=node_x, # Posición X
y=node_y # Posición Y
),
link=dict(
source=source,
target=target,
value=value,
color=link_colors
)
)
])
fig.update_layout(title_text="Flujo de Estudiantes con Posición de Nodos Controlada", font_size=10)
fig.show()
¿Por qué ajustar las posiciones manualmente?
A veces, Plotly puede organizar los nodos de una manera que no es óptima para la legibilidad o la estética, especialmente con muchos nodos o cruces de enlaces. Ajustar `x` e `y` manualmente te da control total sobre el diseño. Por ejemplo, puedes querer que nodos relacionados estén verticalmente alineados o que ciertos flujos sean más prominentes.📊 Un Caso de Uso Real: Análisis del Flujo de Energía
Ahora, apliquemos lo aprendido a un escenario más práctico: la visualización del flujo de energía en un sistema. Usaremos datos ficticios que representan cómo la energía se genera, se transforma y se consume.
Consideremos el siguiente flujo:
- Generación: Solar, Eólica, Nuclear
- Transformación/Transmisión: Red Eléctrica, Almacenamiento
- Consumo: Hogares, Industria, Vehículos Eléctricos
import pandas as pd
import plotly.graph_objects as go
# Datos de flujo de energía
data = {
'source': ['Solar', 'Eólica', 'Nuclear', 'Red Eléctrica', 'Red Eléctrica', 'Red Eléctrica', 'Almacenamiento'],
'target': ['Red Eléctrica', 'Red Eléctrica', 'Red Eléctrica', 'Hogares', 'Industria', 'Almacenamiento', 'Vehículos Eléctricos'],
'value': [50, 70, 80, 60, 90, 30, 20]
}
df_energy = pd.DataFrame(data)
# Obtener todas las etiquetas de nodos únicas
all_nodes = list(pd.unique(df_energy[['source', 'target']].values.ravel('K')))
# Crear un mapeo de etiqueta a índice
label_to_index = {label: i for i, label in enumerate(all_nodes)}
# Convertir source y target a índices numéricos
df_energy['source_id'] = df_energy['source'].map(label_to_index)
df_energy['target_id'] = df_energy['target'].map(label_to_index)
# Definir colores de nodos y enlaces (ejemplo)
node_colors_energy = [
"#FFC300", # Solar
"#DAF7A6", # Eólica
"#FF5733", # Nuclear
"#C70039", # Red Eléctrica
"#900C3F", # Almacenamiento
"#581845", # Hogares
"#A0C4FF", # Industria
"#B8D8F7" # Vehículos Eléctricos
]
link_colors_energy = [
"rgba(255, 195, 0, 0.4)", # Solar -> Red
"rgba(218, 247, 166, 0.4)", # Eólica -> Red
"rgba(255, 87, 51, 0.4)", # Nuclear -> Red
"rgba(199, 0, 57, 0.4)", # Red -> Hogares
"rgba(144, 12, 63, 0.4)", # Red -> Industria
"rgba(88, 24, 69, 0.4)", # Red -> Almacenamiento
"rgba(160, 196, 255, 0.4)" # Almacenamiento -> Vehículos
]
fig = go.Figure(data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=all_nodes,
color=node_colors_energy
),
link=dict(
source=df_energy['source_id'],
target=df_energy['target_id'],
value=df_energy['value'],
color=link_colors_energy
)
)
])
fig.update_layout(title_text="Flujo de Energía en un Sistema (MW)", font_size=12)
fig.show()
En este ejemplo, usamos pandas para gestionar los datos, lo que es muy común en proyectos de ciencia de datos. Primero, recolectamos todos los nodos únicos y luego creamos un diccionario para mapear sus nombres a índices numéricos, que es lo que Plotly espera.
✨ Consejos Avanzados y Buenas Prácticas
- Datos Limpios: Asegúrate de que tus datos de
source,targetyvaluesean consistentes y no contengan errores. Los diagramas de Sankey son sensibles a la calidad de los datos. - Escalabilidad: Para un gran número de nodos y enlaces, el diagrama puede volverse abrumador. Considera agrupar nodos o filtrar flujos menos significativos si la complejidad es muy alta.
- Interactividad: Aprovecha la interactividad de Plotly. Los usuarios pueden hacer zoom, pan y ver detalles al pasar el ratón, lo que es invaluable para explorar datos complejos.
- Colores Significativos: Usa colores para diferenciar categorías de nodos o tipos de flujos, pero no abuses de ellos. La paleta de colores debe ser coherente y añadir valor, no confusión.
- Etiquetas Claras: Las etiquetas de los nodos deben ser concisas y descriptivas.
- Narrativa: Un diagrama de Sankey es una herramienta de storytelling. Úsalo para contar una historia sobre cómo los recursos se mueven y transforman. Acompaña el gráfico con texto explicativo que guíe al lector.
Añadiendo información adicional en los tooltips
Plotly permite personalizar el texto que aparece cuando pasas el ratón sobre los nodos o enlaces (hovertemplate o hoverinfo). Esto puede ser muy útil para mostrar detalles adicionales sin saturar el gráfico.
Por ejemplo, para los enlaces:
# ... (código anterior para df_energy y all_nodes, label_to_index, etc.)
fig = go.Figure(data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=all_nodes,
color=node_colors_energy,
hovertemplate='Nodo: %{label}<br>Flujo Entrante: %{value}<extra></extra>' # Personalizar hover para nodos
),
link=dict(
source=df_energy['source_id'],
target=df_energy['target_id'],
value=df_energy['value'],
color=link_colors_energy,
hovertemplate='Origen: %{source.label}<br>Destino: %{target.label}<br>Cantidad: %{value} MW<extra></extra>' # Personalizar hover para enlaces
)
)
])
fig.update_layout(title_text="Flujo de Energía con Hovers Personalizados", font_size=12)
fig.show()
El hovertemplate utiliza una sintaxis específica de Plotly con placeholders como %{label}, %{value}, %{source.label}, etc., para mostrar información dinámica.
🔄 Flujos Cíclicos y Retroalimentación
Los diagramas de Sankey también pueden representar flujos cíclicos o de retroalimentación, donde el flujo de un nodo puede volver a uno anterior. Plotly gestiona esto automáticamente, aunque la visualización puede requerir un cuidadoso posicionamiento de los nodos para evitar un desorden excesivo.
Considera un proceso donde parte del resultado se recicla o se reintroduce en una etapa anterior.
# Ejemplo de flujo cíclico (simplificado)
labels_cycle = ["Proceso A", "Proceso B", "Producto Final", "Reciclaje"]
source_cycle = [0, 0, 1, 3]
target_cycle = [1, 2, 2, 0] # Reciclaje (3) vuelve a Proceso A (0)
value_cycle = [80, 20, 100, 15] # 15 unidades de reciclaje de vuelta a Proceso A
fig_cycle = go.Figure(data=[
go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=labels_cycle,
color=["lightblue", "lightcoral", "lightgreen", "lightgray"]
),
link=dict(
source=source_cycle,
target=target_cycle,
value=value_cycle,
color=["rgba(173, 216, 230, 0.4)", "rgba(240, 128, 128, 0.4)", "rgba(144, 238, 144, 0.4)", "rgba(211, 211, 211, 0.4)"]
)
)
])
fig_cycle.update_layout(title_text="Diagrama de Sankey con Flujo Cíclico/Reciclaje", font_size=10)
fig_cycle.show()
conclusiones y Siguientes Pasos ✅
Has aprendido a crear y personalizar diagramas de Sankey impactantes con Plotly en Python. Estas visualizaciones son invaluables para comprender y comunicar flujos complejos en una variedad de dominios, desde la economía hasta la biología.
Repaso de los Pasos Clave:
¿Qué Sigue?
- Explora más opciones de Plotly: La documentación de Plotly es muy extensa. Investiga más a fondo
go.Sankeyy otras propiedades delayout. - Datos Reales: Busca conjuntos de datos reales de flujos (ej. migración, energía, finanzas) e intenta visualizarlos.
- Integración: Aprende a integrar estos gráficos interactivos en aplicaciones web con Dash (también de Plotly).
- Animaciones: Para series temporales de flujos, considera cómo podrías animar los diagramas de Sankey.
Esperamos que este tutorial te haya proporcionado las herramientas y la confianza para empezar a revelar el flujo en tus propios datos. ¡La visualización de datos es un arte y una ciencia, y los diagramas de Sankey son una de sus herramientas más elegantes!
Tutoriales relacionados
- Desentrañando Historias con Gráficos de Red: Un Enfoque Práctico en Pythonintermediate25 min
- Unveiling Historias Visuales: Creando Narrativas con Gráficos de Área Apilados en Pythonbeginner15 min
- Visualización Interactiva de Datos con Plotly Express en Python: ¡Crea Dashboards Asombrosos!intermediate18 min
- Visualizando Series Temporales Interactivas con Bokeh en Python: El Clima de tu Ciudadintermediate15 min
- Visualización Creativa con Gráficos de Waffle en Python: Representando Proporciones de Forma Impactanteintermediate15 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!