The seaborn.objects interface

seaborn · Advanced · 15 min

seaborn.objects makes complex layered, faceted plots explicit and composable instead of hunting for function-specific parameters.

seaborn.objects (conventionally import seaborn.objects as so) is a newer, declarative API. You build a so.Plot specification step by step:

(so.Plot(df, x="week", y="minutes", color="plan")
   .add(so.Line(), so.Agg())
   .add(so.Band(), so.Est(errorbar="se"))
   .facet(col="region")
   .label(x="Week", y="Minutes"))

The pieces:

  • Marks draw: Dot, Dots, Line, Lines, Path, Bar, Bars, Area, Band, Range, Dash, Text.
  • Stats transform data before drawing: Agg (mean by default), Est (estimate with error interval), Hist, KDE, Count, Perc, PolyFit.
  • Moves adjust positions: Dodge, Stack, Jitter, Shift, Norm.
  • Plot methods: .add(mark, stat, move, **variables) adds a layer, .facet(col=, row=, wrap=), .pair(x=[...]), .scale(...), .limit(...), .label(...), .layout(size=...), .theme({...}), .share(...).

Each method returns a new Plot, so specifications are immutable and reusable: define a base plot and derive variants. Nothing is drawn until the plot is displayed in a notebook, .show(), .save("file.png"), or compiled with .plot().

Variables can be set on Plot for all layers or on a single .add call. .on(ax) or .on(fig) draws into an existing Matplotlib Axes or figure, so you can mix with classic code.

The API is still marked experimental in 0.13, but it covers most common plots.

Example

import matplotlib
matplotlib.use("Agg")
import seaborn as sns
import seaborn.objects as so
import pandas as pd
import numpy as np

rng = np.random.default_rng(8)
df = pd.DataFrame({"week": np.tile(np.arange(1, 7), 40),
                   "plan": np.repeat(["free", "pro"], 120),
                   "region": np.tile(np.repeat(["eu", "us"], 6), 20)})
df["minutes"] = 20 + 3 * df.week + (df.plan == "pro") * 8 + rng.normal(0, 6, 240)

base = so.Plot(df, x="week", y="minutes", color="plan")
p = (base.add(so.Line(marker="o"), so.Agg())
         .add(so.Band(), so.Est(errorbar="se"))
         .facet(col="region")
         .label(x="Week", y="Minutes per day")
         .layout(size=(8, 3.5)))
plotter = p.plot()                      # compile without showing
print(len(plotter._figure.axes))        # 2: one per region
p.save("objects.png")
print(type(base).__name__, base is p)   # Plot False: methods return new Plots

Remember

  • Compose so.Plot(...) with .add(mark, stat, move) layers
  • Marks draw, stats transform, moves adjust positions
  • Plot methods return new objects; nothing renders until shown, saved or plotted

Watch out for

  • Expecting .add(...) to modify a Plot in place; it returns a new Plot you must keep.

Check yourself

  1. In `so.Plot(df, x='day', y='tip').add(so.Bar(), so.Agg())`, what does `so.Agg()` do?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: seaborn.pydata.org/tutorial/objects_interface.html