Dash: Monitoreo del Fenómeno El Niño
Hace unas semanas quería construir un dashboard rápido para visualizar datos, y en vez de ir directo a mis herramientas de siempre (Streamlit, o armar un frontend con React), decidí probar Dash. El resultado terminó siendo un proyecto que combina dos cosas que me interesan bastante: la simplicidad de construir dashboards en Python, y un tema que como peruano me toca de cerca — el Fenómeno El Niño.
¿Qué es Dash?
Demo:
Cada línea de umbral se agrega con fig.add_hline() — una sola llamada te da la línea punteada, el color, y la anotación con el texto flotando encima. Esto es lo que quiero decir con "se ve increíble sin esfuerzo": no hace falta calcular posiciones de texto ni dibujar nada a mano, Plotly lo resuelve.
También agrego un selector de rango temporal (botones de "1 año", "5 años", "10 años", "Todo") y un range slider debajo del gráfico, con una sola configuración:
fig.update_xaxes(
range=[default_start, last_date],
rangeselector=dict(
buttons=[
dict(count=1, label="1 año", step="year", stepmode="backward"),
dict(count=5, label="5 años", step="year", stepmode="backward"),
dict(count=10, label="10 años", step="year", stepmode="backward"),
dict(step="all", label="Todo"),
],
...
),
rangeslider=dict(visible=True, bgcolor=COLOR_PANEL, bordercolor=COLOR_GRID),
)
Esos botones y el slider son 100% interactivos desde el navegador, sin ningún callback de Dash detrás — vienen incluidos en el objeto Figure de Plotly.
Los KPIs tipo semáforo
Además del gráfico, quería una respuesta rápida a "¿cómo estamos ahora mismo?" — para eso están las dos tarjetas KPI, una para ICEN y otra para RONI, con un color de "semáforo" según el estado:
SEMAFORO_COLOR = {
"El Niño": COLOR_WARM,
"Cálida": COLOR_WARM,
"Cálida débil": COLOR_WARM,
"Neutro": COLOR_TEXT_MUTED,
"Neutra": COLOR_TEXT_MUTED,
"La Niña": COLOR_COLD,
"Fría": COLOR_COLD,
}
def kpi_card(titulo: str, estado: str, valor: float, fecha_label: str) -> html.Div:
color = SEMAFORO_COLOR.get(estado, COLOR_TEXT_MUTED)
return html.Div(
style=_kpi_card_style(color),
children=[
html.H4(titulo, style={...}),
html.H2(estado, style={..., "color": color}),
html.P(f"Valor: {valor:.2f} ({fecha_label})", style={...}),
],
)
SOCIAL SHARE CARD GENERATOR