On this tutorial, we discover the superior visualization capabilities of the XY Python library by constructing interactive, scalable, and extensible charts. We start with XY’s composition mannequin, the place we mix a number of marks, twin axes, annotations, tooltips, legends, themes, and interactive controls inside a single chart declaration. We then work with Pandas DataFrames, faceted layouts, linked viewports, and million-point datasets that robotically swap to density-based rendering for environment friendly exploration. We additionally join browser interactions again to Python by picks and callbacks, replace charts dynamically by streaming, customise visible elements with DOM slots and CSS, and prolong the library with a reusable customized trendline mark. Additionally, we use the Matplotlib-compatible interface and export our visualizations as standalone HTML, SVG, and PNG information.
import subprocess, sys, os
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "xy"], test=True)
WIDGETS_OK = True
attempt:
from google.colab import output as _colab_output
_colab_output.enable_custom_widget_manager()
besides Exception:
WIDGETS_OK = False
import numpy as np
import pandas as pd
import xy
from IPython.show import show, HTML
print("xy", xy.__version__, "| stay widgets:", WIDGETS_OK)
def render(chart, notice=""):
if notice:
show(HTML(f"{notice}
"))
attempt:
show(chart)
besides Exception:
show(HTML(chart.to_html()))
return chart
rng = np.random.default_rng(7)
days = np.arange(180)
pattern = 200 + 0.9 * days + 18 * np.sin(days / 9.0)
income = pattern + rng.regular(0, 12, days.measurement)
sigma = 10 + 6 * np.abs(np.sin(days / 15.0))
conv = 0.06 + 0.02 * np.sin(days / 21.0) + rng.regular(0, 0.003, days.measurement)
peak = int(np.argmax(income))
layered = xy.chart(
xy.error_band(days, income - 1.96 * sigma, income + 1.96 * sigma,
title="95% band", coloration="#7c3aed", opacity=0.16),
xy.line(days, income, title="Income", coloration="#7c3aed", width=2.5,
curve="easy"),
xy.scatter(days[::12], income[::12], title="Weekly test", coloration="#7c3aed",
measurement=7, stroke="#ffffff", stroke_width=1.5),
xy.line(days, conv, title="Conversion", coloration="#f59e0b", width=2,
sprint="dashed", y_axis="y2"),
xy.x_axis(label="Day", grid=True),
xy.y_axis(label="Income (ok)", grid=True, format=",.0f"),
xy.y_axis(id="y2", label="Conversion", facet="proper", grid=False, format=".1%"),
xy.x_band(120, 150, textual content="Marketing campaign", coloration="#22c55e", opacity=0.10),
xy.hline(float(income.imply()), textual content="imply", coloration="#94a3b8"),
xy.callout(float(days[peak]), float(income[peak]), "peak", dx=-60, dy=-40),
xy.legend(loc="higher left", ncols=2, toggle=True),
xy.tooltip(title="Day", format={"y": ",.1f"}),
xy.modebar(True),
xy.theme(palette=["#7c3aed", "#f59e0b"], grid_color="#e6e6ef"),
title="Layered composition · twin axes · annotations",
width=900, peak=440, crosshair=True,
)
render(layered, "1 · Composition mannequin")
We set up and initialize the XY library in Google Colab whereas enabling assist for interactive widgets. We outline a reusable rendering operate that shows stay charts and falls again to standalone HTML when widget assist is unavailable. We then construct a layered visualization with a number of marks, twin axes, annotations, tooltips, legends, themes, and interactive navigation controls.
n = 4000
df = pd.DataFrame({
"x": rng.regular(0, 1, n),
"noise": rng.regular(0, 1, n),
"area": rng.alternative(["North", "South", "East", "West"], n),
})
df["y"] = 2.1 * df["x"] + df["noise"] * 0.9
df["mag"] = np.abs(df["y"])
render(xy.scatter_chart(
xy.scatter("x", "y", coloration="magazine", colormap="plasma",
measurement=5, opacity=0.7, color_domain=(0, 6)),
xy.colorbar(title="|y|"),
xy.x_axis(label="x"), xy.y_axis(label="y"),
knowledge=df, title="Columns resolved by title", width=760, peak=420,
), "2 · DataFrame-driven channels")
render(xy.facet_chart(
xy.scatter("x", "y", coloration="#0ea5e9", measurement=4, opacity=0.6),
by="area", knowledge=df, cols=2,
share_x=True, share_y=True, hyperlink=True, link_select=True,
width=760, peak=220, hole=12, title="Faceted by area",
), "3 · Aspects with linked axes")
N = 1_500_000
r = 6.0 * rng.beta(1.2, 3.0, N)
theta = 2.9 * np.log1p(r) + rng.integers(0, 4, N) * (np.pi / 2) + rng.regular(0, 0.05, N)
huge = xy.scatter_chart(
xy.scatter(r * np.cos(theta), r * np.sin(theta),
coloration=np.exp(-r / 2.2), colormap="magma_r",
density=True,
measurement=2.5, opacity=0.85,
zoom_size_factor=2.6, zoom_opacity=0.95),
xy.colorbar(title="density"),
title=f"{N:,} factors · drag to pan, scroll to zoom",
width=760, peak=520, zoom=True, pan=True, wheel_zoom=True,
)
render(huge, "4 · Million-point density floor")
mem = huge.memory_report()
print(f"canonical f64 held in Python : {mem['canonical_bytes']/1e6:.1f} MB")
print(f"bytes despatched for first paint : {mem['transport_bytes_first_paint']/1e6:.2f} MB "
f"({mem['transport_bytes_per_point']:.3f} B/level)")
print(f"compute backend : {mem['backend']}")
We create a structured Pandas DataFrame and use column names immediately as visualization channels. We generate a color-encoded scatter plot, divide the dataset into linked regional aspects, and protect shared axis habits throughout panels. We additionally visualize 1.5 million factors by XY’s density rendering system and examine its reminiscence utilization and data-transfer effectivity.
sel = huge.select_range(-1.0, 1.0, -1.0, 1.0)
sx, sy = sel.xy(0)
print(f"nselect_range hit {len(sel):,} rows; x array {sx.form}")
print("first rows:", sel.rows(restrict=2))
print("decide(hint=1, index=10):", layered.decide(1, 10))
def on_select(choice):
xs, ys = choice.xy(0)
print(f"[callback] {len(choice):,} rows chosen, imply y = {ys.imply():.3f}")
def on_view_change(payload):
print("[callback] viewport:", payload)
render(xy.scatter_chart(
xy.scatter("x", "y", coloration="#ef4444", measurement=5, opacity=0.7),
knowledge=df, choose=True, on_select=on_select, on_view_change=on_view_change,
title="Shift-drag a field → payload lands in Python",
width=760, peak=380,
), "5 · Choices routed again to the kernel")
stream = xy.line_chart(
xy.line([0.0], [0.0], coloration="#10b981", width=2, title="stay"),
xy.x_axis(label="t"), xy.y_axis(label="worth", area=(-3, 3)),
title="Streaming by way of chart.append()", width=760, peak=320,
)
render(stream, "6 · Streaming")
import time
for ok in vary(1, 60):
t = ok / 3.0
stream.append(0, [t], [float(np.sin(t) + rng.normal(0, 0.08))])
time.sleep(0.03)
We choose precise knowledge factors from the big visualization and retrieve their unique row values immediately from Python. We outline callback features that obtain browser-side picks and viewport modifications whereas holding the underlying knowledge contained in the kernel. We additionally create a streaming line chart and repeatedly append new observations to replace the visualization in actual time.
print("navailable slots:", ", ".be a part of(sorted(xy.CHART_DOM_SLOTS)))
CSS = """
.xy-card {background:#fafaf9;border:1px stable #e7e5e4;border-radius:16px;padding:10px}
.xy-title{font:600 16px/1.2 ui-sans-serif;letter-spacing:-.01em;coloration:#1c1917}
.xy-tip {border-radius:10px;background:#1c1917;coloration:#fafaf9}
"""
show(HTML(f""))
styled = xy.line_chart(
xy.line(days, income, coloration="#111827", width=2,
animation=xy.animation(period=700,
easing=xy.spring(stiffness=180, damping=22))),
xy.x_axis(label="Day"), xy.y_axis(label="Income"),
title="Slot-addressed styling",
class_name="xy-card",
class_names={"title": "xy-title", "tooltip": "xy-tip"},
types={"canvas": {"border-radius": "12px"}},
width=760, peak=360,
)
render(styled, "7 · CSS slots, tokens, spring animation")
def _fit(cols):
x = np.asarray(cols["x"], float); y = np.asarray(cols["y"], float)
b, a = np.polyfit(x, y, 1)
order = np.argsort(x); xs = x[order]
match = a + b * xs
resid = float(np.std(y - (a + b * x)))
return {"x": xs, "y": y[order], "match": match,
"lo": match - 1.96 * resid, "hello": match + 1.96 * resid}
def _build(ctx):
coloration = ctx.choices.get("coloration", "#2563eb")
c, nm = ctx.columns, (ctx.title or "pattern")
return [
xy.error_band(c["x"], c["lo"], c["hi"], coloration=coloration, opacity=0.18, title=f"{nm} CI"),
xy.line(c["x"], c["fit"], coloration=coloration, width=2.5, title=nm),
]
if "trendline" not in xy.registered_marks():
xy.register_mark(xy.MarkPlugin(title="trendline", construct=_build,
columns=("x", "y"), calc=_fit,
doc="OLS match with a 95% band."))
render(xy.chart(
xy.scatter("x", "y", coloration="#94a3b8", measurement=4, opacity=0.5, title="observations"),
xy.mark("trendline", x="x", y="y", coloration="#e11d48", title="OLS"),
xy.legend(loc="higher left"),
knowledge=df, title="Third-party mark variety", width=760, peak=400,
), "8 · Customized mark plugin")
We customise chart elements by steady DOM slots, CSS courses, inline types, and spring-based animations. We outline an odd least-squares calculation that produces a fitted trendline and a 95% confidence band from the provided knowledge. We then register this calculation as a reusable customized XY mark and mix it with built-in scatter, line, error-band, and legend elements.
import xy.pyplot as plt
t = np.linspace(0, 10, 400)
fig, ax = plt.subplots(figsize=(8, 3.5))
ax.plot(t, np.sin(t), "r--", label="sin")
ax.plot(t, np.cos(t), label="cos")
ax.set_xlabel("t"); ax.set_ylabel("amplitude"); ax.set_title("xy.pyplot compatibility")
ax.legend(); ax.grid(True, alpha=0.3)
plt.present()
os.makedirs("out", exist_ok=True)
layered.to_html("out/chart.html")
layered.to_svg("out/chart.svg")
layered.to_png("out/chart.png", scale=2)
for f in ("chart.html", "chart.svg", "chart.png"):
print(f"out/{f}: {os.path.getsize('out/'+f)/1024:.0f} KB")
print("n✅ tutorial full")
We use the xy.pyplot compatibility layer to create plots with acquainted Matplotlib-style instructions. We generate sine and cosine curves, configure labels, titles, legends, and grid settings, and show the ensuing determine. We lastly export the layered chart as standalone HTML, SVG, and high-resolution PNG information and confirm the scale of every generated artifact.
In conclusion, we constructed a complete understanding of how XY helps fashionable interactive visualization workflows immediately from Python. We created layered and faceted charts, analyzed massive datasets effectively, retrieved precise chosen rows from the kernel, streamed new observations into stay visualizations, and customised chart look by themes, animations, CSS courses, and steady DOM slots. We additionally demonstrated how we prolong XY with our personal statistical mark plugin and reuse acquainted Matplotlib-style plotting instructions by the xy.pyplot bridge. We completed with moveable exports that enable us to share charts exterior the pocket book whereas preserving both interactivity or publication-ready graphical high quality.
Take a look at the FULL CODES right here. Additionally, be happy to comply with us on Twitter and don’t overlook to affix our 150k+ML SubReddit and Subscribe to our Publication. Wait! are you on telegram? now you’ll be able to be a part of us on telegram as properly.
Have to companion with us for selling your GitHub Repo OR Hugging Face Web page OR Product Launch OR Webinar and many others.? Join with us
