Altair
Altair expone una API declarativa de gramática de gráficos que compila a Vega-Lite: los gráficos se convierten en especificaciones JSON que puedes versionar, comparar e incrustar en la web.
Receta
Tarjeta de receta de referencia rápida, lista para copiar y pegar.
import altair as alt
import pandas as pd
df = pd.read_csv("sales.csv", parse_dates=["ordered_at"])
chart = (
alt.Chart(df)
.mark_line(point=True)
.encode(x="ordered_at:T", y="sum(revenue):Q", color="region:N")
.properties(width=600, height=300, title="Ingresos por región")
)
chart.save("revenue.json")Cuándo usar esto:
- Especificaciones que deseas tener en git como JSON, no como código de trazado imperativo.
- Gráficos superpuestos (
+,|) con composición legible. - Incrustación en sitios estáticos a través de Vega-Embed.
- Enseñanza de la gramática de visualización sin el código repetitivo de matplotlib.
Ejemplo de trabajo
import altair as alt
import pandas as pd
import numpy as np
rng = np.random.default_rng(42)
df = pd.DataFrame(
{
"region": np.repeat(["East", "West"], 150),
"revenue": rng.normal(150, 35, 300).clip(20),
"units": rng.integers(1, 60, 300),
}
)
base = alt.Chart(df).encode(
x=alt.X("revenue:Q", bin=alt.Bin(maxbins=20), title="Ingresos"),
color="region:N",
)
hist = base.mark_bar(opacity=0.7).properties(width=400, height=250, title="Distribución")
scatter = (
alt.Chart(df)
.mark_circle(size=60, opacity=0.5)
.encode(
x="units:Q",
y="revenue:Q",
color="region:N",
tooltip=["region", "units", "revenue"],
)
.properties(width=400, height=250, title="Unidades vs ingresos")
)
dashboard = alt.hconcat(hist, scatter).resolve_scale(color="shared")
rule = (
alt.Chart(pd.DataFrame({"y": [150]}))
.mark_rule(color="firebrick", strokeDash=[4, 4])
.encode(y="y:Q")
)
layered = scatter + rule
dashboard.save("dashboard.json")
layered.save("scatter_target.json")Lo que esto demuestra:
- Codificación de bin en forma declarativa.
- Concatenación horizontal con escala de color compartida.
- Anotación de regla superpuesta con
+. - Exportación JSON para incrustar.
Inmersión Profunda
Cómo funciona
Chart(data)+mark_*+ canalesencode(x,y,color,tooltip).- Abreviatura
:Qcuantitativo,:Nnominal,:Ttemporal,:Oordinal. - Las transformaciones (
transform_filter,transform_aggregate) permanecen en la especificación. - El compilador emite JSON de Vega-Lite renderizado por JS en el navegador o PNG a través de
altair_saver.
Tipos de Codificación
| Abreviatura | Tipo |
|---|---|
:Q | Cuantitativo |
:N | Nominal (categorías) |
:O | Categorías ordenadas |
:T | Temporal |
Notas de Python
import altair as alt
alt.data_transformers.disable_max_rows() # solo cuando aceptas incrustaciones grandes
alt.renderers.enable("json") # el renderizador predeterminado del notebook varía según la versiónTrampas
- Límite predeterminado de 5000 filas - Altair muestrea fotogramas grandes. Solución: agrega en pandas/Polars primero o deshabilita las filas máximas a sabiendas.
- Datos anchos - múltiples columnas y necesitan
transform_foldomelt. Solución: organiza en formato largo previamente. - Ordenar ejes nominales - el orden alfabético predeterminado desordena los meses. Solución:
sort=["Ene", "Feb", ...]o:Ocon orden. - Guardar PNG sin dependencias - necesita
vl-convertoaltair_saver. Solución: envía JSON al front-end o instala el convertidor en CI. - Selecciones interactivas en datos enormes - lentas en el lado del cliente. Solución: filtra los datos en el lado del servidor antes del gráfico.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| Plotly | Rica interactividad incorporada | Quieres portabilidad de la especificación Vega-Lite |
| matplotlib | Flujos de trabajo de impresión maduros | La especificación JSON es el entregable |
| ggplot (plotnine) | Migración de R ggplot | La incrustación de Vega es el objetivo |
| seaborn | EDA rápida con pandas | La serialización de especificaciones importa |
Preguntas Frecuentes
¿Por qué Vega-Lite JSON?
- El front-end puede renderizar sin volver a ejecutar Python.
- Las especificaciones se comparan limpiamente en la revisión del código.
¿Cómo hago facetas?
alt.Chart(df).mark_point().encode(x="x", y="y").facet("region:N")¿Cómo filtro en la especificación?
alt.Chart(df).transform_filter(alt.datum.revenue > 100).mark_bar().encode(...)¿Cómo combino gráficos?
hconcat,vconcat, operadores|y&superponen o concatenan.resolve_scalealinea ejes y leyendas.
¿Puede Altair leer Polars?
- Pasa Polars a través de
pl.DataFramecuando sea compatible o.to_pandas().
¿Cómo agrego una línea de media?
rule = alt.Chart(df).mark_rule(strokeDash=[4,4]).encode(y="mean(revenue):Q")
chart + rule¿Cómo incrusto en HTML?
- Guarda JSON; usa la etiqueta de script Vega-Embed en una página estática.
- O
chart.save("out.html")cuando el renderizador HTML esté configurado.
¿Qué pasa con la accesibilidad?
- Proporciona tooltips y títulos de eje significativos.
- No confíes solo en el color: usa también forma o facetas.
¿Cómo configuro el esquema de color?
.encode(color=alt.Color("region:N", scale=alt.Scale(scheme="set2")))¿Es Altair bueno para mapas?
- Se admite geo básico a través de
mark_geoshape. - El GIS pesado a menudo requiere herramientas dedicadas.
Relacionado
- Plotly - alternativa interactiva
- Conceptos básicos de visualización - elección de gráficos
- Mejores prácticas de visualización - color accesible
- Graficar datos grandes - agregar primero
Versiones de la pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.