plotlet v0.6.2

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)
["Jan","Feb","Mar","Apr","May","Jun"]

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)
["Thur","Fri","Sat","Sun"]

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.

Aesthetics & scales →