No existe una única librería de gráficos "mejor" en Python, y quien te diga lo contrario te está vendiendo algo. La respuesta honesta es que el campo se reparte entre un puñado de herramientas, cada una de las cuales gana en una tarea concreta: un gráfico estático con calidad de publicación, una estadística en una sola línea, un dashboard interactivo, una especificación declarativa que puedes versionar, o un gráfico que tiene que sobrevivir a cien millones de puntos. Esta review recorre las librerías que importan, en qué es genuinamente buena cada una, dónde se rompe y —porque este sitio trata de construir en Python para mercados— cómo manejan las velas y las series temporales grandes.

Cada recuento de estrellas, cifra de descargas y licencia que aparece abajo se contrastó con fuentes primarias (GitHub, PyPI, documentación oficial) a mediados de 2026. Cuando un número es el mejor caso autoinformado por un proveedor, se señala como tal.

Estrellas de GitHub de las librerías de gráficos de Python principales a mediados de 2026 — Matplotlib lidera con ~22,9k, con Bokeh, Plotly y Seaborn pisándole los talones.

El modelo mental: estático vs. interactivo

La primera bifurcación es si la salida es una imagen estática (PNG/SVG/PDF, renderizada una sola vez) o una figura interactiva (HTML/JS, con pan-zoom-hover en un navegador).

La segunda bifurcación —que solo te muerde cuando tus datos crecen— es dónde se dibujan los puntos: en el navegador (del lado del cliente, WebGL) o preagregados en el servidor en una imagen. Esa distinción es toda la historia del "nivel de escala" más abajo, y es la que la mayoría de las reviews se salta.

Matplotlib — el cimiento sobre el que todo se apoya

Matplotlib es la roca madre del trazado en Python. No es solo una librería; es el motor de renderizado sobre el que Seaborn, los valores por defecto de Plotnine, mplfinance y una docena más se construyen. Su licencia es permisiva —oficialmente "basada en la licencia PSF" y compatible con BSD—, así que puedes integrarla en un producto propietario y venderlo sin pensarlo dos veces (documentación de la licencia).

Fortalezas. Control total. Si puedes describir una marca sobre un lienzo 2D, Matplotlib puede dibujarla, y exporta un PDF/SVG vectorial nítido para impresión. Está instalado en todas partes y cualquier error que llegues a encontrar ya tiene una respuesta en Stack Overflow.

Debilidades. La API es célebremente bicéfala —una interfaz pyplot con estado al estilo MATLAB y una interfaz orientada a objetos Figure/Axes— y los tutoriales las mezclan sin pudor, que es justo el motivo por el que "why you hate matplotlib" es todo un género. Los valores por defecto están anticuados, y darle a un gráfico un aspecto moderno cuesta unas cuantas líneas de código de verdad.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(df.index, df["close"], lw=1.2)
ax.set_title("BTC-USD daily close")
fig.savefig("btc.png", dpi=150, bbox_inches="tight")

Salida de Matplotlib — una serie de precios de BTC de ejemplo con medias móviles de 20 y 50 días más un panel de volumen, dibujada eje a eje.

Úsalo cuando necesites una figura estática lista para imprimir, o estés construyendo una herramienta de más alto nivel y quieras un lienzo que controles por completo.

Seaborn — gráficos estadísticos sin el boilerplate

Seaborn es una capa fina y con criterio propio sobre Matplotlib (BSD-3-Clause) que convierte diez líneas de pelea con los ejes en una. "Proporciona una interfaz de alto nivel para dibujar gráficos estadísticos atractivos" y se integra de forma estrecha con pandas — distribuciones, regresiones, heatmaps y small-multiples facetados son todos una sola llamada.

import seaborn as sns
sns.set_theme()
sns.lineplot(data=returns, x="date", y="ret", hue="symbol")

Salida de Seaborn — un heatmap de correlación de retornos de activos en una sola llamada, el tipo de gráfico estadístico que Seaborn vuelve trivial.

Fortalezas. Los mejores valores por defecto para estadística de su categoría; precioso desde el primer momento; el primer recurso obvio para el análisis exploratorio de datos.

Debilidades. Hereda la naturaleza estática de Matplotlib (sin interactividad) y, cuando necesitas un gráfico para el que no tiene función, de todos modos terminas bajando a Matplotlib en crudo. Es una capa de comodidad, no una vía de escape del motor.

Úsalo cuando estés haciendo EDA sobre un DataFrame y quieras heatmaps de correlación, distribuciones o gráficos de regresión rápido.

Plotly — el interactivo por defecto

Plotly.py es la opción interactiva más adoptada. Tiene licencia MIT, está construida sobre plotly.js, y las cifras no dejan lugar a dudas: en torno a 18,6k estrellas en GitHub y unos 1,24 mil millones de descargas históricas en PyPI — del orden de 61 millones de descargas en los últimos 30 días (PyPI · estadísticas de descargas). Los tooltips al pasar el cursor, el zoom, el pan y el alternado de la leyenda vienen gratis, y la misma figura se renderiza en un notebook, en una app de Dash o en un archivo HTML estático.

import plotly.graph_objects as go

fig = go.Figure(go.Candlestick(
    x=df.index, open=df.open, high=df.high, low=df.low, close=df.close,
))
fig.update_layout(title="BTC-USDT", xaxis_rangeslider_visible=False)
fig.show()

Salida de Plotly — una vela interactiva con una media móvil de 20 días; el pan, el zoom y el hover están activos en la versión de navegador.

Fortalezas. Interactividad con cero JavaScript; tipos de gráfico financiero de primera clase (go.Candlestick, go.Ohlc); el camino hacia un dashboard completo (Dash) es corto.

Debilidades. El bundle de plotly.js es pesado — un coste real para sitios sensibles al tiempo de carga de la página (análisis de tiempos de bundle). Y hay un techo de renderizado duro: con trazas WebGL (go.Scattergl) puedes representar hasta ~1 millón de puntos, pero los navegadores solo permiten de 8 a 16 contextos WebGL por página, así que en la práctica obtienes de 4 a 8 figuras WebGL antes de chocar con "Too many active WebGL contexts" (documentación de rendimiento de Plotly). El zoom/pan interactivo fluido aguanta de forma realista hasta ~100–200k puntos.

Úsalo cuando quieras gráficos interactivos o dashboards, sobre todo financieros, y tus series tengan de miles a unos pocos millones de puntos.

Bokeh — interactivo pensado para datos grandes y en streaming

Bokeh (BSD-3-Clause, ~20,4k estrellas / 4,3k forks) es el principal rival interactivo de Plotly, con un centro de gravedad distinto: es "una librería de visualización interactiva para navegadores web modernos" orientada a conjuntos de datos grandes y en streaming y a apps dirigidas desde el servidor (el servidor de Bokeh puede empujar actualizaciones en vivo a un gráfico a través de un websocket).

Una salvedad honesta que el marketing no te dará: el "alto rendimiento" es en parte autodescripción. Informes del mundo real muestran que el hover/los tooltips se atascan con conjuntos de datos tan pequeños como ~50k puntos, así que no es automáticamente rápido con datos enormes — sigues teniendo que recurrir a la agregación (más abajo). Trata la ventaja de Bokeh como streaming y arquitectura de apps, no como recuento bruto de puntos.

from bokeh.plotting import figure, show

p = figure(x_axis_type="datetime", title="BTC-USD", height=350)
p.line(df["date"], df["close"])
show(p)

Úsalo cuando estés construyendo un dashboard que se actualiza en vivo o una app de datos dirigida desde Python y quieras control del lado del servidor sobre la interactividad.

Altair — una gramática declarativa de gráficos

Altair es una librería declarativa: describes qué codificar (esta columna a x, aquella al color) y el motor Vega-Lite decide cómo dibujarlo. Los gráficos son especificaciones JSON, lo que los hace componibles y amigables con los diffs.

Salida de Altair — la misma serie de precios como un gráfico declarativo de área más línea, generado a partir de una concisa especificación Vega-Lite.

La trampa con la que tropieza todo recién llegado: por defecto, Altair se niega a trazar más de 5.000 filas, lanzando un MaxRowsError. Es una barrera deliberada (Altair incrusta los datos como JSON en la especificación), no una incapacidad para manejar datos — y levantarla es cuestión de una línea:

import altair as alt
alt.data_transformers.disable_max_rows()   # o usa el backend VegaFusion para ~100k+

alt.Chart(df).mark_line().encode(x="date:T", y="close:Q")

Es una fuente de frustración recurrente precisamente porque el error aparece sobre lo que se siente como un frame "pequeño" de 35k filas (documentación de grandes conjuntos de datos).

Úsalo cuando valores especificaciones de gráficos concisas, declarativas y reproducibles y tus datos sean modestos — o estés dispuesto a cablear VegaFusion para los frames más grandes.

Plotnine y Pygal — completando el cuadro

python from plotnine import ggplot, aes, geom_line (ggplot(df, aes("date", "close")) + geom_line())

Salida de Plotnine — los mismos datos al estilo de la gramática de gráficos de ggplot2, instantáneamente familiar para cualquiera que venga de R.

Cuando tus datos crecen: el nivel de escala

Aquí es donde las elecciones ingenuas se vienen abajo. Una vez que pasas del millón de puntos, no puedes simplemente entregárselos al navegador. (Para ser precisos sobre un mito: los navegadores pueden representar ~1M de puntos WebGL — lo que se degrada es la fluidez interactiva, no es un crash duro.) Dos estrategias lo arreglan:

1. Rasterización del lado del servidor — Datashader. En lugar de enviar puntos al navegador, Datashader (BSD-3-Clause) los agrupa en una cuadrícula 2D de tamaño fijo y renderiza esa cuadrícula como una imagen, "preservando fielmente la distribución de los datos". Su cifra estrella: mil millones de puntos en alrededor de un segundo en un portátil de 16 GB, escalando out-of-core y a la GPU vía Dask (introducción · guía de grandes datos de HoloViews). Trata el número de mil millones de puntos por segundo como un mejor caso del proveedor — pero el enfoque (reagrupar en cada zoom/pan) es genuinamente el correcto para datos densos.

import datashader as ds, datashader.transfer_functions as tf

cvs = ds.Canvas(plot_width=900, plot_height=400)
agg = cvs.points(df, "t", "price")     # df puede ser un frame de Dask más grande que la RAM
img = tf.shade(agg)

2. Submuestreo dependiente de la vista — plotly-resampler. Esto conserva toda la interactividad de Plotly pero solo renderiza los puntos que realmente puedes ver. Su agregación por defecto MinMaxLTTB reduce cada traza a ~1.000 puntos trazados para la vista actual y luego vuelve a buscar datos a medida que haces zoom — la demo visualiza más de 110 millones de puntos de datos de esta manera (artículo).

from plotly_resampler import FigureResampler
import plotly.graph_objects as go

fig = FigureResampler(go.Figure())
fig.add_trace(go.Scattergl(name="price"), hf_x=ts, hf_y=price)  # más de 100M de puntos
fig.show_dash()

Regla general: scatter/heatmap denso de millones de puntos → Datashader; serie temporal interactiva larga → plotly-resampler.

Graficar datos de mercado: velas y OHLC

Para un flujo de trabajo enfocado en trading, lo que destaca es mplfinance — el paquete de gráficos financieros de la organización Matplotlib. Toma un DataFrame de pandas con un DatetimeIndex y columnas Open/High/Low/Close y dibuja gráficos de velas, OHLC, línea, Renko y Point & Figure, con medias móviles y volumen incorporados:

import mplfinance as mpf
mpf.plot(df, type="candle", mav=(20, 50), volume=True, style="charles")

Más allá de mplfinance:

La comparación de un vistazo

Librería Tipo Licencia Interactivo Mejor para Ojo con
Matplotlib Estático PSF/compatible BSD No Control total, impresión/PDF Verboso, valores por defecto anticuados
Seaborn Estático BSD-3 No EDA estadístico Baja a Matplotlib para lo inusual
Plotly Interactivo MIT Dashboards, gráficos financieros Bundle pesado; techo WebGL de ~1M de puntos
Bokeh Interactivo BSD-3 Streaming / apps de datos No es rápido por sí solo con datos grandes
Altair Interactivo BSD-3 Especificaciones declarativas y reproducibles Límite por defecto de 5.000 filas
Plotnine Estático MIT No Memoria muscular de ggplot2 Solo estático
Pygal SVG Open source (LGPL) Ligero Gráficos vectoriales limpios en la web De nicho; no para datos grandes
Datashader Ráster en servidor BSD-3 Vía HoloViews 10⁶–10⁹ puntos Una imagen, no marcas vectoriales
mplfinance Estático Estilo BSD (org mpl) No Velas / OHLC Estático; combínalo con Plotly para interactividad

Cifras de popularidad verificadas a mediados de 2026: Plotly ≈18,6k estrellas / ≈1,24B descargas; Bokeh ≈20,4k estrellas / 4,3k forks. Los recuentos de estrellas y descargas se mueven constantemente — trátalos como instantáneas, y recuerda que las descargas brutas de PyPI incluyen CI y mirrors, así que sobreestiman la adopción humana.

Cómo elegir, en una sola frase

Elige la que encaje con el trabajo, no la que tenga más estrellas. La mayoría de los proyectos reales terminan usando dos o tres de estas juntas — Seaborn para la exploración, Plotly para el dashboard, mplfinance para el informe del backtest — y ese es el resultado correcto, no un fracaso en estandarizar.


Metodología: las afirmaciones de esta review se contrastaron con fuentes primarias (repositorios de GitHub de los proyectos, PyPI y documentación oficial) y se verificaron de forma adversarial; las cifras son instantáneas de mediados de 2026. Los números de rendimiento marcados como cifras del proveedor (los mil millones de puntos de Datashader, los 110M de plotly-resampler) son mejores casos reproducibles, no benchmarks independientes.