Altair: gramática de gráficos declarativa
Altair es una biblioteca de visualización basada en la gramática de gráficos de Vega-Lite. Su filosofía es declarativa: en lugar de especificar cómo dibujar el gráfico paso a paso (como en Matplotlib), se describe qué datos mostrar y qué codificaciones visuales aplicar (ejes, colores, formas, tamaños). Altair genera internamente una especificación JSON que el navegador renderiza como un gráfico interactivo.
La principal ventaja de Altair frente a Plotly es su sistema de selecciones interactivas vinculadas: se pueden conectar múltiples gráficos para que la selección en uno filtre automáticamente los demás, sin necesidad de callbacks manuales:
import streamlit as st
import altair as alt
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
"x": range(50),
"y": np.cumsum(np.random.randn(50)) + 10,
"categoria": np.random.choice(["A", "B", "C"], 50)
})
# Gráfico de dispersión básico
chart = alt.Chart(df).mark_circle(size=60).encode(
x=alt.X("x:Q", title="Índice"),
y=alt.Y("y:Q", title="Valor"),
color=alt.Color("categoria:N", title="Categoría"),
tooltip=["x", "y", "categoria"]
).properties(
title="Gráfico de dispersión con Altair",
width="container",
height=350
)
st.altair_chart(chart, use_container_width=True)
En la codificación de Altair, los sufijos de tipo (:Q para cuantitativo, :N para nominal, :O para ordinal, :T para temporal) indican cómo debe interpretar Altair cada campo del DataFrame, determinando automáticamente la escala y el eje adecuados.
flowchart TD
A[Visualización declarativa] --> B{"Caso?"}
B -->|Datos tabulares| C[Altair gramatica encode mark]
B -->|Especificación JSON| D[st.vega_lite_chart spec]
B -->|Grafo de nodos| E[st.graphviz_chart DOT]
C --> F[mark_circle mark_bar mark_line]
F --> G[encode x y color tooltip]
G --> H[selection_point selection_interval]
H --> I[Vincular gráficos con add_params]
D --> J[Pasa dict directamente al renderer]
E --> K[Lenguaje DOT con flecha A B]
K --> L[Visualiza dependencias o flujo]
I --> M[Dashboard interactivo declarativo]
J --> M
L --> M
Tipos de marcas (marks) en Altair
Las marcas definen la representación visual de cada dato. Altair soporta mark_point, mark_circle, mark_bar, mark_line, mark_area, mark_rect, mark_tick y mark_text, entre otras. Un patrón habitual es combinar múltiples marcas con el operador + para superponer capas:
import streamlit as st
import altair as alt
import pandas as pd
import numpy as np
df = pd.DataFrame({
"mes": range(1, 13),
"ventas": np.random.randint(5000, 15000, 12),
"objetivo": [10000] * 12
})
# Gráfico de barras con línea de objetivo
barras = alt.Chart(df).mark_bar(color="#FF4B4B", opacity=0.8).encode(
x=alt.X("mes:O", title="Mes"),
y=alt.Y("ventas:Q", title="Ventas (€)"),
tooltip=["mes", "ventas"]
)
objetivo = alt.Chart(df).mark_line(
color="#1F77B4", strokeDash=[5, 5], strokeWidth=2
).encode(
x="mes:O",
y="objetivo:Q"
)
# Combinar gráficos con el operador +
st.altair_chart(barras + objetivo, use_container_width=True)
Selecciones interactivas
Una de las características más diferenciadoras de Altair es la vinculación interactiva entre gráficos. Las selecciones permiten al usuario arrastrar un rectángulo, hacer clic en un punto o seleccionar valores de un eje, y que esa selección se propague automáticamente a otros gráficos vinculados:
import streamlit as st
import altair as alt
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
"x": np.random.randn(200),
"y": np.random.randn(200),
"categoria": np.random.choice(["Tipo A", "Tipo B", "Tipo C"], 200),
"valor": np.random.uniform(10, 100, 200)
})
# Selector de intervalo interactivo
seleccion = alt.selection_interval()
# Gráfico de dispersión con selección
scatter = alt.Chart(df).mark_circle().encode(
x=alt.X("x:Q"),
y=alt.Y("y:Q"),
color=alt.condition(
seleccion,
alt.Color("categoria:N"),
alt.value("lightgray")
),
size=alt.Size("valor:Q"),
tooltip=["x", "y", "categoria", "valor"]
).add_params(seleccion).properties(
title="Selecciona una región",
width=400, height=300
)
# Histograma vinculado que se filtra con la selección
histograma = alt.Chart(df).mark_bar().encode(
x=alt.X("categoria:N"),
y=alt.Y("count()"),
color=alt.Color("categoria:N")
).transform_filter(seleccion).properties(
title="Distribución de la selección",
width=400, height=300
)
# Mostrar lado a lado
st.altair_chart(scatter | histograma, use_container_width=True)
st.vega_lite_chart: especificación JSON directa
Para usuarios que conocen la especificación JSON de Vega-Lite, st.vega_lite_chart permite pasarla directamente:
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame({"x": range(10), "y": np.random.randn(10).cumsum()})
st.vega_lite_chart(df, {
"mark": {"type": "line", "point": True},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
},
"title": "Gráfico con Vega-Lite directo"
}, use_container_width=True)
El operador | (pipe) coloca los gráficos uno al lado del otro horizontalmente, mientras que & los apila verticalmente. Esto permite crear paneles de análisis exploratorio conectados sin necesidad de gestionar el layout manualmente.
st.graphviz_chart: grafos y diagramas de dependencias
st.graphviz_chart renderiza grafos de nodos y aristas descritos en el lenguaje DOT de Graphviz. Es la herramienta adecuada para visualizar pipelines de datos, árboles de decisión, diagramas de arquitectura, grafos de dependencias y cualquier estructura que se represente naturalmente como un conjunto de nodos conectados por aristas:
import streamlit as st
# Pipeline de ML como grafo de dependencias
st.graphviz_chart("""
digraph pipeline_ml {
rankdir=LR
node [shape=box, style=filled]
Datos [fillcolor="#E3F2FD"]
Limpieza [fillcolor="#E8F5E9"]
Features [fillcolor="#E8F5E9"]
Entrenamiento [fillcolor="#FFF3E0"]
Validacion [fillcolor="#FFF3E0"]
Despliegue [fillcolor="#FCE4EC"]
Monitoreo [fillcolor="#FCE4EC"]
Datos -> Limpieza
Limpieza -> Features
Features -> Entrenamiento
Entrenamiento -> Validacion
Validacion -> Despliegue [label="AUC > 0.90"]
Validacion -> Entrenamiento [label="AUC ≤ 0.90", style=dashed]
Despliegue -> Monitoreo
Monitoreo -> Entrenamiento [label="Drift detectado", style=dashed]
}
""")
# Árbol de herencia de clases
st.graphviz_chart("""
digraph herencia {
node [shape=record]
Animal [label="{Animal|+ nombre: str\\n+ edad: int|+ sonido()\\n+ moverse()}"]
Mamifero [label="{Mamifero|+ pelaje: str|+ amamantar()}"]
Ave [label="{Ave|+ envergadura: float|+ volar()}"]
Perro [label="{Perro||+ ladrar()}"]
Gato [label="{Gato||+ maullar()}"]
Animal -> Mamifero
Animal -> Ave
Mamifero -> Perro
Mamifero -> Gato
}
""")
Examen de visualización con todas las herramientas
import streamlit as st
import altair as alt
import plotly.express as px
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
st.title("Comparativa de bibliotecas de visualización")
herramienta = st.segmented_control(
"Biblioteca",
["Altair", "Plotly", "Matplotlib/Seaborn"],
default="Plotly"
)
df = px.data.iris()
if herramienta == "Altair":
chart = alt.Chart(df).mark_circle().encode(
x="sepal_length:Q", y="sepal_width:Q",
color="species:N", tooltip=list(df.columns)
).properties(title="Iris — Altair", width="container")
st.altair_chart(chart, use_container_width=True)
elif herramienta == "Plotly":
fig = px.scatter(df, x="sepal_length", y="sepal_width",
color="species", title="Iris — Plotly")
st.plotly_chart(fig, use_container_width=True)
else:
fig, ax = plt.subplots(figsize=(8, 5))
sns.scatterplot(data=df, x="sepal_length", y="sepal_width",
hue="species", ax=ax)
ax.set_title("Iris — Matplotlib/Seaborn")
st.pyplot(fig)
plt.close(fig)
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Streamlit es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Streamlit
Explora más contenido relacionado con Streamlit y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Crear gráficos interactivos declarativos con Altair y st.altair_chart. Usar la gramática de gráficos de Altair con mark_point, mark_bar y mark_line. Implementar selecciones interactivas y vinculación entre gráficos con Altair. Renderizar especificaciones Vega-Lite directamente con st.vega_lite_chart. Visualizar grafos de nodos y aristas con st.graphviz_chart y lenguaje DOT.