1. Introduction
The mental model in five minutes: charts are journals,
data is long-form, aes() maps columns to aesthetics, and
rendering is deterministic. Every snippet on this page is executed
on every build — the figures are its output.
A first chart
A chart is a journal: every method call
records what you asked for, and nothing is drawn until you render. In a
notebook, c.show() displays the figure;
c.to_svg() returns the SVG as text. The same journal always
renders to the same bytes, on any machine.
import plotlet as pt
from plotlet import aes
df = {"month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
"sales": [12, 15, 14, 18, 21, 19]}
c = pt.chart(df, aes(x="month", y="sales"),
title="monthly sales", ylabel="units (k)")
c.add_line()
c.add_scatter(size=3)
Long-form data in, aes() maps the columns
plotlet expects tidy tables — a plain dict of
columns, a pandas frame, or a polars frame all work. Column mappings go
in aes(...): each aesthetic names one column. Four small
datasets ship for experimenting (pt.list_datasets() →
anscombe, flights, penguins,
tips).
tips = pt.load_dataset("tips")
c = pt.chart(tips, aes(x="total_bill", y="tip", color="day"),
title="tips", xlabel="total bill ($)", ylabel="tip ($)",
legend=True)
c.add_scatter(size=3, alpha=0.7)
Declare aesthetics once, layer many marks
The aes(...) on the chart is inherited
by every artist you add, so layering is just more calls — here
the scatter and the per-group regression share x,
y and color from the chart, and each layer
carries only its own styling.
tips = pt.load_dataset("tips")
c = pt.chart(tips, aes(x="total_bill", y="tip", color="time"),
xlabel="total bill ($)", ylabel="tip ($)", legend=True)
c.add_scatter(size=3, alpha=0.6)
c.add_regression()
Distributions across groups
The statistical artists take the same long-form table. Overlaying a boxplot and the raw points is two bare calls once the chart carries the aesthetics.
tips = pt.load_dataset("tips")
c = pt.chart(tips, aes(x="day", y="total_bill"),
ylabel="total bill ($)")
c.xscale("category", order=["Thur", "Fri", "Sat", "Sun"])
c.add_boxplot()
c.add_strip(size=2.5, alpha=0.4)
Rendering and saving
to_svg() is the native output —
text as paths, no font dependencies. save_png() rasterizes
through resvg (prebuilt wheels, no system libraries),
save_pdf() needs the optional cairosvg
extra, and save_html() wraps the SVG for a browser.
df = {"x": [1, 2, 3, 4], "y": [2, 4, 3, 5]}
c = pt.chart(df, aes(x="x", y="y"), title="export")
c.add_line()
svg_text = c.to_svg() # the canonical, byte-stable output
# c.save_svg("figure.svg") # or: save_png, save_pdf, save_html
Where next
The remaining chapters go deeper: scales and aesthetics, labels and legends, multi-panel composition, sectors and circular coordinates, color and themes, and the reproducibility and AI-tooling story. Or jump straight to the cookbook and copy something.