or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

categorical-plots.mdcolor-palettes.mddistribution-plots.mdgrid-plots.mdindex.mdinteractive-widgets.mdmatrix-plots.mdobjects-interface.mdrelational-plots.mdstyling-themes.mdutilities.md

objects-interface.mddocs/

0

# Objects Interface

1

2

A declarative, object-oriented interface for creating statistical graphics following the Grammar of Graphics approach. The objects interface provides composable classes that can be combined to build customized visualizations through method chaining and layer composition.

3

4

**Core Concept**: Specify what you want to show rather than how to draw it. Build plots by combining data, marks, statistical transformations, positional adjustments, and scales.

5

6

## Core Imports

7

8

```python

9

from seaborn.objects import Plot

10

```

11

12

Common imports for marks, stats, and moves:

13

14

```python

15

from seaborn.objects import (

16

Plot,

17

# Marks

18

Dot, Dots, Line, Lines, Path, Bar, Bars, Area, Band, Text,

19

# Stats

20

Stat, Agg, Est, Count, Hist, KDE,

21

# Moves

22

Move, Dodge, Jitter, Stack, Shift, Norm,

23

# Scales

24

Scale, Continuous, Nominal, Boolean, Temporal

25

)

26

```

27

28

## Capabilities

29

30

### Plot Orchestration

31

32

The main interface for declarative plotting that orchestrates data, marks, stats, and scales.

33

34

```python { .api }

35

class Plot:

36

def __init__(self, *args, data=None, **variables):

37

"""

38

Initialize plot with data source and variable mappings.

39

40

Parameters:

41

- data: DataFrame or dict with columnar data

42

- **variables: mappings from variables to data columns (x=, y=, color= etc.)

43

"""

44

45

def add(self, mark, *transforms, orient=None, legend=True, label=None, data=None, **variables):

46

"""

47

Add a layer with mark and optional transforms.

48

49

Parameters:

50

- mark: Mark instance defining visual representation

51

- *transforms: Stat and/or Move instances for data transformation

52

- orient: "x" or "y" orientation, inferred if not specified

53

- legend: whether to include layer in legend

54

- label: label for legend entry

55

- data: override data source for this layer

56

- **variables: additional variable mappings for this layer

57

58

Returns:

59

Plot instance for method chaining

60

"""

61

62

def facet(self, col=None, row=None, order=None, wrap=None):

63

"""

64

Create subplots with conditional data subsets.

65

66

Parameters:

67

- col: variable for subplot columns

68

- row: variable for subplot rows

69

- order: dict specifying order of facet levels

70

- wrap: wrap columns after this number

71

72

Returns:

73

Plot instance for method chaining

74

"""

75

76

def pair(self, x=None, y=None, wrap=None, cross=True):

77

"""

78

Create subplots by pairing multiple x/y variables.

79

80

Parameters:

81

- x: list of variables for x-axis pairing

82

- y: list of variables for y-axis pairing

83

- wrap: wrap columns after this number

84

- cross: if False, pair variables in order rather than crossing

85

86

Returns:

87

Plot instance for method chaining

88

"""

89

90

def scale(self, **scales):

91

"""

92

Specify data-to-visual property mappings.

93

94

Parameters:

95

- x, y: Scale instances for coordinate mappings

96

- color, fill, linestyle, etc.: Scale instances for aesthetic mappings

97

98

Returns:

99

Plot instance for method chaining

100

"""

101

102

def share(self, **shares):

103

"""

104

Control sharing of axis limits/ticks across subplots.

105

106

Parameters:

107

- x, y: True (share all), False (independent), or "col"/"row" (share within)

108

109

Returns:

110

Plot instance for method chaining

111

"""

112

113

def limit(self, **limits):

114

"""

115

Control range of visible data.

116

117

Parameters:

118

- x, y: tuple of (min, max) values or single values for symmetric limits

119

120

Returns:

121

Plot instance for method chaining

122

"""

123

124

def label(self, title=None, legend=None, **variables):

125

"""

126

Control labels for axes, legends, and subplots.

127

128

Parameters:

129

- title: main plot title

130

- legend: legend title

131

- **variables: axis labels (x=, y=, color= etc.)

132

133

Returns:

134

Plot instance for method chaining

135

"""

136

137

def layout(self, size=None, engine=None, extent=None):

138

"""

139

Control figure size and layout.

140

141

Parameters:

142

- size: tuple of (width, height) in inches

143

- engine: layout engine ("constrained" or "tight")

144

- extent: subplot area as fraction of figure

145

146

Returns:

147

Plot instance for method chaining

148

"""

149

150

def theme(self, config):

151

"""

152

Control plot appearance via matplotlib rc parameters.

153

154

Parameters:

155

- config: dict of matplotlib rcParams

156

157

Returns:

158

Plot instance for method chaining

159

"""

160

161

def on(self, target):

162

"""

163

Use existing matplotlib figure/axes for drawing.

164

165

Parameters:

166

- target: matplotlib Figure, Axes, or SubFigure

167

168

Returns:

169

Plot instance for method chaining

170

"""

171

172

def save(self, loc, **kwargs):

173

"""

174

Compile and save plot to file.

175

176

Parameters:

177

- loc: output filename or path-like object

178

- **kwargs: additional arguments passed to matplotlib savefig

179

180

Returns:

181

Plot instance for method chaining

182

"""

183

184

def show(self, **kwargs):

185

"""

186

Compile and display plot.

187

188

Parameters:

189

- **kwargs: additional arguments passed to matplotlib show

190

"""

191

```

192

193

### Mark Classes

194

195

Visual representation of data through matplotlib artists.

196

197

```python { .api }

198

class Mark:

199

"""Base class for visual representations of data."""

200

def _mappable_props(self):

201

"""Properties that can be mapped from data."""

202

203

def _grouping_props(self):

204

"""Properties used for grouping data."""

205

206

class Dot(Mark):

207

"""A mark suitable for dot plots or scatter plots."""

208

marker: str = "o"

209

pointsize: float = 6

210

stroke: float = 0.75

211

color: str = "C0"

212

alpha: float = 1

213

fill: bool = True

214

edgecolor: str = "auto"

215

edgealpha: float = "auto"

216

edgewidth: float = 0.5

217

edgestyle: str = "-"

218

219

class Dots(Mark):

220

"""Dot mark optimized for handling overplotting with stroke-defined points."""

221

marker: str = "o"

222

pointsize: float = 4

223

stroke: float = 0.75

224

color: str = "C0"

225

alpha: float = 1

226

fill: bool = True

227

fillcolor: str = "auto"

228

fillalpha: float = 0.2

229

230

class Line(Mark):

231

"""Connect data points with lines, sorting along orientation axis."""

232

color: str = "C0"

233

alpha: float = 1

234

linewidth: float = "auto"

235

linestyle: str = "-"

236

marker: str = ""

237

pointsize: float = "auto"

238

fillcolor: str = "auto"

239

edgecolor: str = "auto"

240

edgewidth: float = "auto"

241

242

class Lines(Mark):

243

"""Faster line mark using matplotlib LineCollection for many lines."""

244

color: str = "C0"

245

alpha: float = 1

246

linewidth: float = "auto"

247

linestyle: str = "-"

248

249

class Path(Mark):

250

"""Connect data points in order they appear without sorting."""

251

# Same properties as Line

252

253

class Range(Lines):

254

"""Oriented line marks between min/max values."""

255

# Inherits properties from Lines

256

257

class Dash(Lines):

258

"""Line mark as oriented segments for each datapoint."""

259

width: float = 0.8

260

261

class Bar(Mark):

262

"""Bar mark drawn between baseline and data values."""

263

color: str = "C0"

264

alpha: float = 0.7

265

fill: bool = True

266

edgecolor: str = "auto"

267

edgealpha: float = 1

268

edgewidth: float = "auto"

269

edgestyle: str = "-"

270

width: float = 0.8

271

baseline: float = 0

272

273

class Bars(Mark):

274

"""Optimized bar mark with defaults for histograms."""

275

# Similar properties to Bar with histogram-optimized defaults

276

277

class Area(Mark):

278

"""Fill mark drawn from baseline to data values."""

279

color: str = "C0"

280

alpha: float = 0.2

281

fill: bool = True

282

edgecolor: str = "auto"

283

edgealpha: float = 1

284

edgewidth: float = "auto"

285

edgestyle: str = "-"

286

baseline: float = 0

287

288

class Band(Mark):

289

"""Fill mark representing interval between min and max values."""

290

color: str = "C0"

291

alpha: float = 0.2

292

fill: bool = True

293

edgecolor: str = "auto"

294

edgealpha: float = 1

295

edgewidth: float = 0

296

edgestyle: str = "-"

297

298

class Text(Mark):

299

"""Textual mark to annotate or represent data values."""

300

text: str = ""

301

color: str = "k"

302

alpha: float = 1

303

fontsize: float = "auto"

304

halign: str = "center"

305

valign: str = "center_baseline"

306

offset: float = 4

307

```

308

309

### Statistical Transformations

310

311

Apply statistical transforms before plotting.

312

313

```python { .api }

314

class Stat:

315

"""Base class for statistical transformations."""

316

group_by_orient: bool = False

317

318

def __call__(self, data, groupby, orient, scales):

319

"""Apply statistical transform to data subgroups."""

320

321

class Agg(Stat):

322

"""Aggregate data along value axis using given method."""

323

func: str | callable = "mean"

324

group_by_orient: bool = True

325

326

class Est(Stat):

327

"""Calculate point estimate and error bar interval."""

328

func: str | callable = "mean"

329

errorbar: str | tuple = ("ci", 95)

330

n_boot: int = 1000

331

seed: int | None = None

332

group_by_orient: bool = True

333

334

class Count(Stat):

335

"""Count distinct observations within groups."""

336

group_by_orient: bool = True

337

338

class Hist(Stat):

339

"""Bin observations, count them, optionally normalize/cumulate."""

340

stat: str = "count" # "count", "density", "percent", "probability", "frequency"

341

bins: str | int | list = "auto"

342

binwidth: float | None = None

343

binrange: tuple | None = None

344

common_norm: bool | list = True

345

common_bins: bool | list = True

346

cumulative: bool = False

347

discrete: bool = False

348

349

class KDE(Stat):

350

"""Compute univariate kernel density estimate."""

351

bw_adjust: float = 1

352

bw_method: str | float | callable = "scott"

353

common_norm: bool | list = True

354

common_grid: bool | list = True

355

gridsize: int | None = 200

356

cut: float = 3

357

cumulative: bool = False

358

359

class Perc(Stat):

360

"""Replace data values with percentile ranks."""

361

k: int = 100

362

method: str = "linear"

363

364

class PolyFit(Stat):

365

"""Fit a polynomial regression of given order."""

366

order: int = 2

367

gridsize: int = 100

368

```

369

370

### Positional Adjustments

371

372

Make positional adjustments to reduce overplotting or achieve specific layouts.

373

374

```python { .api }

375

class Move:

376

"""Base class for positional transforms."""

377

group_by_orient: bool = True

378

379

def __call__(self, data, groupby, orient, scales):

380

"""Apply positional transform and return modified data."""

381

382

class Jitter(Move):

383

"""Random displacement along axes to reduce overplotting."""

384

width: float = "auto" # Relative to mark width

385

x: float = 0 # Absolute displacement in x

386

y: float = 0 # Absolute displacement in y

387

seed: int | None = None

388

389

class Dodge(Move):

390

"""Displacement/narrowing of overlapping marks along orientation."""

391

empty: str = "keep" # "keep", "drop", "fill"

392

gap: float = 0

393

by: list | None = None

394

395

class Stack(Move):

396

"""Displacement of overlapping bars/areas along value axis."""

397

# No additional parameters

398

399

class Shift(Move):

400

"""Displacement of all marks with same magnitude/direction."""

401

x: float = 0

402

y: float = 0

403

404

class Norm(Move):

405

"""Divisive scaling on value axis after aggregating within groups."""

406

func: str | callable = "max"

407

where: str | None = None # Query string for subset

408

by: list | None = None # Variables for aggregation groups

409

percent: bool = False

410

group_by_orient: bool = False

411

```

412

413

### Scale Classes

414

415

Control mappings between data values and visual properties.

416

417

```python { .api }

418

class Scale:

419

"""Base class for data-to-visual mappings."""

420

def __call__(self, data):

421

"""Transform data through the scale pipeline."""

422

423

def tick(self, **kwargs):

424

"""Configure tick selection."""

425

426

def label(self, **kwargs):

427

"""Configure label formatting."""

428

429

class Continuous(Scale):

430

"""Numeric scale supporting norms and functional transforms."""

431

values: tuple | str | None = None

432

trans: str | None = None # "log", "sqrt", "symlog", etc.

433

434

def tick(self, locator=None, *, at=None, upto=None, count=None, every=None, between=None, minor=None):

435

"""Configure tick selection for axis/legend."""

436

437

def label(self, formatter=None, *, like=None, base=None, unit=None):

438

"""Configure tick label appearance."""

439

440

class Nominal(Scale):

441

"""Categorical scale without relative importance/magnitude."""

442

values: tuple | str | list | dict | None = None

443

order: list | None = None

444

445

def tick(self, locator=None):

446

"""Configure tick selection."""

447

448

def label(self, formatter=None):

449

"""Configure label formatting."""

450

451

class Boolean(Scale):

452

"""Scale with discrete domain of True/False values."""

453

values: tuple | list | dict | None = None

454

455

def tick(self, locator=None):

456

"""Configure tick selection."""

457

458

def label(self, formatter=None):

459

"""Configure label formatting."""

460

461

class Temporal(Scale):

462

"""Scale for date/time data."""

463

# No transforms available for temporal data

464

465

def tick(self, locator=None, *, upto=None):

466

"""Configure tick selection for dates."""

467

468

def label(self, formatter=None, *, concise=False):

469

"""Configure date label formatting."""

470

```

471

472

## Usage Examples

473

474

### Basic Plot Construction

475

476

```python

477

import seaborn.objects as so

478

import pandas as pd

479

480

# Load data

481

tips = sns.load_dataset("tips")

482

483

# Basic scatter plot

484

(

485

so.Plot(tips, x="total_bill", y="tip")

486

.add(so.Dot())

487

.show()

488

)

489

```

490

491

### Multi-layer Plot with Statistics

492

493

```python

494

# Scatter plot with regression line

495

(

496

so.Plot(tips, x="total_bill", y="tip")

497

.add(so.Dot(alpha=0.5))

498

.add(so.Line(), so.PolyFit(order=1))

499

.label(

500

title="Bill vs Tip with Regression",

501

x="Total Bill ($)",

502

y="Tip ($)"

503

)

504

.show()

505

)

506

```

507

508

### Grouped Data with Aesthetics

509

510

```python

511

# Grouped scatter plot with color mapping

512

(

513

so.Plot(tips, x="total_bill", y="tip", color="time")

514

.add(so.Dot())

515

.scale(color=so.Nominal(values=["skyblue", "orange"]))

516

.show()

517

)

518

```

519

520

### Histogram with Custom Styling

521

522

```python

523

# Histogram with custom bins and styling

524

(

525

so.Plot(tips, x="total_bill")

526

.add(so.Bar(), so.Hist(bins=20))

527

.layout(size=(8, 5))

528

.label(

529

title="Distribution of Total Bills",

530

x="Total Bill ($)",

531

y="Count"

532

)

533

.show()

534

)

535

```

536

537

### Faceted Plot

538

539

```python

540

# Faceted scatter plots

541

(

542

so.Plot(tips, x="total_bill", y="tip")

543

.add(so.Dot(alpha=0.7))

544

.facet(col="time", row="smoker")

545

.label(title="Tips by Time and Smoking Status")

546

.show()

547

)

548

```

549

550

### Advanced Layering with Moves

551

552

```python

553

# Box plot with jittered points

554

(

555

so.Plot(tips, x="day", y="total_bill")

556

.add(so.Range(color="gray"), so.Est(errorbar="sd"))

557

.add(so.Dot(alpha=0.3), so.Jitter(width=0.3))

558

.show()

559

)

560

```

561

562

### Multiple Variables and Pairing

563

564

```python

565

# Pair plot using objects interface

566

numeric_cols = ["total_bill", "tip", "size"]

567

(

568

so.Plot(tips[numeric_cols])

569

.pair(cross=True)

570

.add(so.Dot(alpha=0.5))

571

.show()

572

)

573

```

574

575

### Custom Scales and Transformations

576

577

```python

578

# Log-scale plot with custom color palette

579

(

580

so.Plot(tips, x="total_bill", y="tip", color="size")

581

.add(so.Dot())

582

.scale(

583

x=so.Continuous(trans="log"),

584

color=so.Continuous(values=("lightblue", "darkred"))

585

)

586

.show()

587

)

588

```

589

590

### Stacked Bar Chart

591

592

```python

593

# Stacked bar chart with custom colors

594

(

595

so.Plot(tips, x="day", color="smoker")

596

.add(so.Bar(), so.Count(), so.Stack())

597

.scale(color=so.Nominal(values=["lightcoral", "steelblue"]))

598

.show()

599

)

600

```

601

602

### Text Annotations

603

604

```python

605

# Scatter plot with text labels

606

(

607

so.Plot(tips.head(10), x="total_bill", y="tip")

608

.add(so.Dot())

609

.add(so.Text(text="size"), text="size", offset=8)

610

.show()

611

)

612

```

613

614

## Workflow Pattern

615

616

The typical workflow follows this pattern:

617

618

1. **Initialize**: `so.Plot(data, x=..., y=..., **aesthetics)`

619

2. **Add Layers**: `.add(Mark(), Stat(), Move())` - can chain multiple

620

3. **Configure Scales**: `.scale(x=Scale(), color=Scale(), ...)`

621

4. **Setup Subplots**: `.facet()` or `.pair()` if needed

622

5. **Customize**: `.label()`, `.layout()`, `.theme()`, `.limit()`, `.share()`

623

6. **Render**: `.show()` or `.save()`

624

625

Each method returns a new Plot instance, enabling flexible method chaining and reusable plot specifications.

626

627

## Types

628

629

```python { .api }

630

# Data types

631

DataFrame = pandas.DataFrame

632

Series = pandas.Series

633

ArrayLike = numpy.ndarray | list

634

635

# Property value types

636

Mappable = Any # Direct values, data column references, or special mappings

637

ColorSpec = str | tuple # Color names, hex codes, RGB tuples

638

MarkerSpec = str # Matplotlib marker codes

639

LineStyleSpec = str | tuple # Matplotlib linestyle codes

640

641

# Scale value specifications

642

ScaleValues = tuple | str | list | dict | None

643

TransformSpec = str | tuple[callable, callable] | None

644

645

# Layout specifications

646

SizeSpec = tuple[float, float] # (width, height) in inches

647

LimitSpec = tuple[float, float] | float # (min, max) or symmetric limit

648

```