API Reference¶
Every rendering backend exposes the same plot, so switching canvases is a
one-line import change. The backend-agnostic statistics and the column
summaries live at the top level with no plotting dependency.
One API, many canvases
import pavement.matplotlib as pavement # or .bokeh / .plotly / .holoviews
pavement.plot([1, 2, 3, 4, 5])
pavement.svg is the one exception: it draws single-row sparklines
(spark), not multi-row plots.
Top-level package (pavement)¶
The package root re-exports the pure-Python statistics and the headline
summary entry point — no backend required.
core
¶
Backend-agnostic pavement statistics.
The pure-math core of the package: quantile computation, the quantile
values that define 1D and 2D pavement plots, and the column summaries
(tally_stats, proportion_stats). Nothing here imports a plotting
library, so it is the shared foundation every backend
(pavement.matplotlib, pavement.holoviews, pavement.plotly,
pavement.bokeh) builds on. The top-level pavement package
re-exports everything in __all__.
quantiles
¶
quantiles(
data: Iterable[float],
levels: Sequence[float],
weights: Sequence[float] | None = None,
presorted: bool = False,
) -> list[float]
Compute Type 2 quantiles, optionally weighted.
Type 2 is the discontinuous quantile definition that averages two adjacent values when a level lands exactly on an order statistic. See https://robjhyndman.com/papers/sample_quantiles.pdf.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values to take quantiles of. Sorted internally unless
presorted is True. Missing values ( |
required |
levels
|
sequence of float
|
Quantile levels in [0, 1], strictly increasing. |
required |
weights
|
sequence of float
|
Positive weights parallel to data. If None, each value contributes equally. |
None
|
presorted
|
bool
|
If True, data (and weights) are assumed already sorted by data in ascending order; the internal sort is skipped. A monotonicity check still runs and raises if the claim is false. |
False
|
Returns:
| Type | Description |
|---|---|
list of float
|
One value per entry in levels, in the same order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If levels is not strictly increasing in [0, 1]; if weights is given and its length doesn't match data; if data is empty (or holds only missing values); if data is not sorted when presorted is True; or if any weight is not positive. |
Source code in src/pavement/core.py
pavement_stats
¶
pavement_stats(
data: Iterable[float],
bins: int | None = 4,
weights: Sequence[float] | None = None,
presorted: bool = False,
) -> list[float]
Compute the quantile values that define a single pavement plot.
Wraps quantiles to turn a bin count into the corresponding
evenly-spaced quantile levels (0, 1/bins, ..., 1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values to summarize. Missing values ( |
required |
bins
|
int or None
|
Number of equal-mass bins. Yields |
4
|
weights
|
sequence of float
|
Positive weights parallel to data. If None, each value contributes equally. Ignored when bins is None, since every point is shown regardless of weight. |
None
|
presorted
|
bool
|
Passed through to |
False
|
Returns:
| Type | Description |
|---|---|
list of float
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If bins is less than 1; if data is empty (or holds only
missing values); if data is not sorted when presorted is
True; or for any reason raised by |
See Also
quantiles : The underlying quantile computation.
Source code in src/pavement/core.py
pavement_stats2d
¶
pavement_stats2d(
x: Iterable[float],
y: Iterable[float],
weights: Sequence[float] | None = None,
bins: int = 4,
x_bins: int | None = None,
y_bins: int | None = None,
first_split: Literal["x", "y"] = "x",
) -> dict[str, Any]
Compute the box edges for a 2D pavement plot.
Sort the data along the first_split axis and partition it into
primary_bins chunks of equal weight. Within each chunk, sort
along the other axis and compute secondary_bins equal-weight
quantiles. Every cell of the resulting grid holds the same
fraction of the data, 1 / (x_bins * y_bins).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
iterable of float
|
Paired coordinates. Must have the same length. |
required |
y
|
iterable of float
|
Paired coordinates. Must have the same length. |
required |
weights
|
sequence of float
|
Positive weights, one per (x, y) pair. Used for both the partition step and the inner quantile step. |
None
|
bins
|
int
|
Default number of bins along each axis. |
4
|
x_bins
|
int
|
Override bins for the respective axis. |
None
|
y_bins
|
int
|
Override bins for the respective axis. |
None
|
first_split
|
('x', 'y')
|
Which axis to partition first. |
'x'
|
Returns:
| Type | Description |
|---|---|
dict
|
When first_split is |
Raises:
| Type | Description |
|---|---|
ValueError
|
If x and y have different lengths or are empty; if weights has a length that doesn't match; if x_bins or y_bins is less than 1; if there are fewer data points than the primary-axis bin count; or if a chunk ends up empty (which can happen with heavily skewed weights). |
See Also
quantiles : The underlying 1D quantile computation.
Source code in src/pavement/core.py
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | |
tally_stats
¶
Count how a column breaks down into distinct, repeated, and missing.
A backend-agnostic summary of a column (a list of values, typically one
column of a table). Unlike pavement_stats, which summarizes the
distribution of numeric values, this looks at the column's make-up and
works on values of any type.
Each value is sorted into exactly one of three buckets, so the three counts always sum to the total:
- missing —
None,NaN, pandasNA/NaT, and the like (see_is_missing); - distinct — the count of distinct present values (each distinct value contributes 1, on its first occurrence); and
- repeated — the remaining present values, each a repeat of a value already counted as distinct.
A fourth count, once, is also returned: how many of the distinct
values appear exactly once in the column (often called "unique"). It
is a sub-count of distinct (once <= distinct), overlapping it
rather than adding to the three-bucket total.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable
|
The column's values, of any type. Need not be numeric or hashable; unhashable values fall back to equality-based grouping. |
required |
Returns:
| Type | Description |
|---|---|
dict of str to int
|
|
See Also
pavement.svg.tally : Render this summary as an inline SVG strip.
Source code in src/pavement/core.py
proportion_stats
¶
Value counts of a column, descending by frequency.
A backend-agnostic summary in the spirit of pandas value_counts():
how a column's present values divide up by how often each occurs.
Missing values (see _is_missing) are dropped, like
value_counts(dropna=True); their number is reported separately.
Where tally_stats summarizes a column's make-up (distinct / repeated /
missing), this exposes the shape of its value distribution — the input
a proportion plot draws.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable
|
The column's values, of any type. Need not be hashable; unhashable values fall back to equality-based grouping. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
|
See Also
pavement.svg.proportion : Render these counts as an inline SVG strip. tally_stats : The companion distinct/repeated/missing summary.
Source code in src/pavement/core.py
Static plots (pavement.matplotlib)¶
matplotlib
¶
Static pavement plots with matplotlib.
The matplotlib backend draws pavements as matplotlib artists on an Axes.
Beyond the shared plot API (single, wide, or tidy data; a rug with
bins=None; orientation), this backend adds three things the
interactive backends don't have: 2D pavements (plot2d), a single-strip
marginal (margin) with rich inside/outside placement, and a borderless,
word-sized inline image (spark).
The backend-agnostic statistics live in pavement.core; the shared row
geometry in pavement._geometry.
draw_pavement
¶
draw_pavement(
values: Sequence[float],
position: float = 1,
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = True,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
line_props: Mapping[str, Any] | None = None,
box_props: Mapping[str, Any] | None = None,
data: Sequence[float] | None = None,
ax: Axes | None = None,
) -> dict[str, Any]
Draw a single pavement row from precomputed quantile values.
Renders one tick per distinct value perpendicular to the value
axis and a box outline spanning values[0] to values[-1]. A
value that repeats (a sign the data is concentrated there) reaches
past the box as a tassel, so every line is drawn exactly once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
sequence of float
|
Quantile values in ascending order, as returned by
|
required |
position
|
float
|
Center of the row along the axis perpendicular to the value
axis. For |
1
|
width
|
float
|
Total thickness of the box outline (perpendicular to the value axis). |
0.6
|
tassel_extent
|
float
|
How far the tassel marks extend beyond the box, perpendicular
to the value axis. Unrelated to matplotlib's |
0.05
|
show_tassels
|
bool
|
If False, suppress the tassel marks even at repeated values. |
False
|
show_box
|
bool or None
|
How to draw the long box edges (the borders parallel to the value
axis, perpendicular to the value ticks). |
True
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'vertical' puts values on the y-axis (matplotlib's boxplot default); 'horizontal' puts them on the x-axis. |
'vertical'
|
line_props
|
dict
|
Line2D properties (color, linewidth, linestyle, alpha, ...)
passed through to the underlying |
None
|
box_props
|
dict
|
If given, a filled |
None
|
data
|
sequence of float
|
The raw values values was computed from. Only the auto box
( |
None
|
ax
|
matplotlib Axes
|
Axes to draw on. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Maps component name to the artist added to the axes:
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If values is empty, or if orientation is not 'vertical' or 'horizontal'. |
See Also
pavement_stats : Compute the values to pass in. plot : One-call convenience that combines stats and drawing.
Source code in src/pavement/matplotlib.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
plot
¶
plot(
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
value_label: str | None = None,
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
line_props: Mapping[str, Any]
| Sequence[Mapping[str, Any]]
| None = None,
box_props: Mapping[str, Any]
| Sequence[Mapping[str, Any]]
| None = None,
ax: Axes | None = None,
) -> list[dict[str, Any]]
Draw one or more pavement rows.
The matplotlib backend's headline function — the counterpart of
pavement.bokeh.plot, pavement.plotly.plot, and
pavement.holoviews.plot. Accepts the same three input shapes:
- A 1D sequence of values: a single row.
- A sequence of 1D sequences: one row per dataset, at positions
(matching matplotlib's
boxplot:data[0]at the smallest position). - A 1D sequence plus categories: tidy/long form. The data is split by category and rendered as in the wide form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
sequence of float, or sequence of iterables of float
|
The values to plot. Shape determines which mode is used. |
required |
weights
|
sequence
|
Positive weights. Must match the shape of data: flat for a single row or tidy form, nested for wide form. |
None
|
positions
|
sequence of float
|
Position of each row along the axis perpendicular to the
value axis. Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data, parallel to data. If given, data is treated as tidy/long form and split by category. |
None
|
labels
|
sequence
|
One label per row, in row order. In tidy form, also selects
which categories to include and their order. When given (or in
tidy form), the rows are ticked on the position axis — the
x-axis for |
None
|
bins
|
int, None, or sequence of (int or None)
|
Number of equal-mass bins per row. A scalar applies to every
row; a sequence sets each row's bin count individually and
must have length equal to the number of rows. None shows all
the data for that row instead of binning it (see
|
4
|
widths
|
float or sequence of float
|
Thickness of each row's box outline. A scalar applies to every row; a sequence sets each row's width individually and must have length equal to the number of rows. |
0.6
|
tassel_extent
|
float
|
How far the tassel marks extend beyond the box, perpendicular
to the value axis. Unrelated to matplotlib's |
0.05
|
show_tassels
|
bool
|
If False, suppress tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges (the borders
parallel to the value axis). None (the default) draws them for a
binned row and omits them for a rug ( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'vertical' puts values on the y-axis (matplotlib's boxplot default); 'horizontal' puts them on the x-axis. |
'vertical'
|
value_label
|
str
|
If given, label the value axis (y for vertical, x otherwise).
The shared name for this across backends; matplotlib leaves the
axis unlabelled by default ( |
None
|
color
|
str or sequence of str
|
Per-row color convenience. A single color applies to every row; a sequence sets each row and must match the number of rows. It tints the lines and, unless box_props is given for that row, draws a translucent fill of the same color (see fill_alpha). Defaults to None: black lines and no fill, unless line_props / box_props say otherwise. For full control use those instead; a per-row line_props color overrides color. |
None
|
fill_alpha
|
float
|
Opacity of the fill drawn for a row that has a color but no explicit box_props. Ignored when no such fill is drawn. |
0.3
|
line_props
|
dict or sequence of dict
|
Per-row line styling. A single dict applies to every row; a
sequence sets each row individually and must have length equal
to the number of rows. See |
None
|
box_props
|
dict or sequence of dict
|
Per-row background fill. A single dict applies to every row; a
sequence sets each row individually and must have length equal
to the number of rows. Takes precedence over color for the
fill. See |
None
|
ax
|
matplotlib Axes
|
Axes to draw on. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
list of dict
|
One artist dict per row, in the same order as the rows. Each
dict has the shape returned by |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color,
labels, line_props, or box_props is given as a sequence
with the wrong length; or for any reason raised by the
underlying |
See Also
pavement_stats : Compute quantile values for one dataset. draw_pavement : Render one row from precomputed values. pavement.bokeh.plot : The Bokeh equivalent.
Source code in src/pavement/matplotlib.py
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | |
spark
¶
spark(
data: Sequence[float],
weights: Sequence[float] | None = None,
bins: int | None = 4,
orientation: Literal[
"vertical", "horizontal"
] = "horizontal",
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
color: str | None = None,
fill_alpha: float = 0.3,
line_props: Mapping[str, Any] | None = None,
box_props: Mapping[str, Any] | None = None,
figsize: tuple[float, float] | None = None,
dpi: float = 200,
pad: float = 0.0,
transparent: bool = True,
path: str | None = None,
) -> Figure
Render a single pavement as a borderless inline "sparkline" image.
A spark is a pavement stripped to its ink: one row drawn on its own figure, with no axes, ticks, labels, or surrounding whitespace, so the box and tassels run right to the edges of the image. The main use is to save a small PNG and drop it inline in text, sized to sit among words like one of Tufte's sparklines.
Unlike plot, this draws exactly one distribution (a 1D sequence of
values) and owns its figure — it creates one rather than drawing on
a shared ~matplotlib.axes.Axes. It defaults to 'horizontal' so
the value axis runs left-to-right like the surrounding text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
sequence of float
|
The values to summarize as a single pavement row. |
required |
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
bins
|
int or None
|
Number of equal-mass bins. None shows all the data instead of
binning it (see |
4
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'horizontal' (the default here,
unlike |
'vertical'
|
width
|
float
|
Thickness of the box outline, perpendicular to the value axis. Only its ratio to tassel_extent matters — the figure is scaled to fit whatever is drawn. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box at repeated values. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw the two long box edges. None (the default) draws
them when binned and omits them for a rug ( |
None
|
color
|
str
|
Tints the lines and, unless box_props is given, draws a translucent fill of the same color (see fill_alpha). Defaults to black lines and no fill. |
None
|
fill_alpha
|
float
|
Opacity of the fill drawn when color is given without an explicit box_props. |
0.3
|
line_props
|
dict
|
Line2D properties for the ticks and box edges. See
|
None
|
box_props
|
dict
|
Background fill properties; takes precedence over color for
the fill. See |
None
|
figsize
|
(float, float)
|
Figure size in inches. Defaults to a word-sized strip —
|
None
|
dpi
|
float
|
Dots per inch, high enough that the small image stays crisp in print. With the default figsize a horizontal spark is about 280x60 pixels. |
200
|
pad
|
float
|
Extra breathing room around the drawn geometry, as a fraction of its extent on each axis. Defaults to none: the box runs flush to the image edge (the half-stroke needed to keep the outermost lines from being clipped is always added on top of this, so a flush edge still shows its full thickness). Raise it to inset the pavement within the image. |
0.0
|
transparent
|
bool
|
Draw on a transparent background (and save with transparency), so the strip blends into whatever it's placed on. |
True
|
path
|
str
|
If given, the figure is saved here (e.g. a |
None
|
Returns:
| Type | Description |
|---|---|
Figure
|
The figure holding the spark. The caller is responsible for
closing it (e.g. |
See Also
plot : Draw one or more pavement rows on a shared Axes. draw_pavement : The underlying single-row renderer.
Source code in src/pavement/matplotlib.py
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | |
margin
¶
margin(
data: Iterable[float],
axis: Literal["x", "y"] = "x",
where: str | None = None,
bins: int | None = 4,
weights: Sequence[float] | None = None,
pad: float = 0.03,
size: float = 0.04,
expand_margins: bool = True,
show_tassels: bool = False,
show_box: bool | None = None,
line_props: Mapping[str, Any] | None = None,
box_props: Mapping[str, Any] | None = None,
clip_on: bool = False,
ax: Axes | None = None,
) -> dict[str, Any]
Draw a pavement plot in the margin of an existing plot.
A marginal pavement is a richer drop-in for a rug plot: it shows the 1D distribution of one variable as a thin strip just outside the axes frame, aligned with the data on that axis.
The strip is drawn with a blended transform, so it stays pinned
to the edge at a fixed thickness — the same for x- and y-axis
marginals — regardless of the data range on the other axis. By
default it sits just outside the frame (clip_on is False) on
the side opposite the tick labels — above the axes for
axis='x', to the right for axis='y'. The where argument
moves it to any edge, inside or outside the frame.
Call this after the main plot so the data-axis limits are
already set; the marginal aligns to whatever limits the axes
has when it is drawn. For axis='x' with where='top', if
the axes already has a title, it is lifted clear of the marginal
— so set the title before calling this.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values whose distribution to summarize. |
required |
axis
|
('x', 'y')
|
Which axis the data belongs to. |
'x'
|
where
|
str
|
Which side of the axes to place the strip on, optionally
prefixed with 'inside' or 'outside' (e.g. 'bottom',
'inside top', 'outside left'). The side is 'top' or 'bottom'
for |
None
|
bins
|
int or None
|
Number of equal-mass bins. None shows all the data instead of
binning it (see |
4
|
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
pad
|
float
|
Gap between the axes frame and the box, as a fraction of the axes height (aspect-scaled for y-axis marginals, like size). |
0.03
|
size
|
float
|
Thickness of the box, as a fraction of the axes height. y-axis marginals are scaled by the axes aspect ratio so they render at the same physical thickness as x-axis ones. |
0.04
|
expand_margins
|
bool
|
For an 'inside' placement, expand the axes margins on the
perpendicular axis so the strip does not overlap the data.
No effect for 'outside' placements. Mirrors the argument of
the same name on seaborn's |
True
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw the two long box edges. None (the default) draws
them when binned and omits them for a rug ( |
None
|
line_props
|
dict
|
Line2D properties for the box edges. Defaults to
|
None
|
box_props
|
dict
|
If given, a background fill is drawn behind the strip. See
|
None
|
clip_on
|
bool
|
Whether to clip the marginal to the axes box. False (the default) lets it render in the exterior margin. |
False
|
ax
|
matplotlib Axes
|
Axes to draw on. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The artist dict from |
Raises:
| Type | Description |
|---|---|
ValueError
|
If axis is not 'x' or 'y', or where is not valid for the given axis. |
See Also
plot : Draw a pavement in the main data area. draw_pavement : The underlying single-row renderer.
Source code in src/pavement/matplotlib.py
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | |
draw_pavement2d
¶
draw_pavement2d(
stats: Mapping[str, Any],
line_props: Mapping[str, Any] | None = None,
box_props: Mapping[str, Any] | None = None,
ax: Axes | None = None,
) -> dict[str, Any]
Draw a 2D pavement from precomputed stats.
Renders every box edge. Where adjacent columns (or rows, for
first_split='y') share a boundary along the primary axis,
the shared line is drawn once per side, which is invisible for
line art but means each side's segment spans only its own
column's (or row's) extent along the secondary axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stats
|
dict
|
Output of |
required |
line_props
|
dict
|
Line2D properties passed through to |
None
|
box_props
|
dict
|
If given, a filled |
None
|
ax
|
matplotlib Axes
|
Axes to draw on. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Maps component name to the artists added to the axes:
|
See Also
pavement_stats2d : Compute the stats dict to pass in. plot2d : One-call convenience that combines stats and drawing.
Source code in src/pavement/matplotlib.py
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | |
plot2d
¶
plot2d(
x: Iterable[float],
y: Iterable[float],
weights: Sequence[float] | None = None,
bins: int = 4,
x_bins: int | None = None,
y_bins: int | None = None,
first_split: Literal["x", "y"] = "x",
line_props: Mapping[str, Any] | None = None,
box_props: Mapping[str, Any] | None = None,
ax: Axes | None = None,
) -> dict[str, Any]
Draw a 2D pavement plot from paired data.
Equivalent to draw_pavement2d(pavement_stats2d(...)). Every
cell of the resulting grid holds an equal share of the data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
iterable of float
|
Paired coordinates. Must have the same length. |
required |
y
|
iterable of float
|
Paired coordinates. Must have the same length. |
required |
weights
|
sequence of float
|
Positive weights, one per (x, y) pair. |
None
|
bins
|
int
|
Default number of bins along each axis. |
4
|
x_bins
|
int
|
Override bins for the respective axis. |
None
|
y_bins
|
int
|
Override bins for the respective axis. |
None
|
first_split
|
('x', 'y')
|
Which axis to partition first. |
'x'
|
line_props
|
dict
|
Line2D properties for all box edges. Defaults to
|
None
|
box_props
|
dict
|
If given, a background fill is drawn behind every cell, with
these properties applied uniformly. See |
None
|
ax
|
matplotlib Axes
|
Axes to draw on. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The artist dict from |
See Also
pavement_stats2d : Compute the stats without drawing. draw_pavement2d : Render from a stats dict. plot : The 1D equivalent.
Source code in src/pavement/matplotlib.py
Inline SVG sparklines (pavement.svg)¶
Self-contained <svg> strings — no plotting library, no JavaScript. This is
where summary, spark, tally, and proportion live.
svg
¶
Inline, interactive pavement sparklines as self-contained SVG.
Where pavement.matplotlib.spark renders a borderless pavement to a
raster image for print, this backend emits the same idea as a string of
SVG you can drop straight into HTML, Markdown, or an email — no plotting
library, no JavaScript bundle, no CDN. The returned <svg> is the
artifact.
That makes it the natural fit for an inline sparkline:
- Vector and themeable. Lines default to
currentColor, so the spark inherits the surrounding text color (dark mode included), and it stays crisp at any size.vector-effect="non-scaling-stroke"keeps the box outline a constant width however small the spark is scaled. - Sizes with the text. By default the root carries
height: 1em; width: auto, sospark(values)drops into a sentence and tracks the font size like a word. - Interactive with zero JavaScript. Every equal-mass bin is a hover
target carrying its value range, percentile band, and value share in a
native
<title>tooltip — the same hover text the Bokeh and Plotly backends show — and each quantile tick carries its single value. A small rug (bins=None) makes every value hoverable; a dense one falls back to a single whole-spark summary instead (seetick_hover_limit) — a spark is read value-by-value or summarised, never both. An inline<style>adds CSS hover feedback: the bin or value line under the cursor highlights, signalling the interactivity. Both optional.
The pavement itself is single-row only (spark); richer multi-row or
marginal pavements belong to the matplotlib and interactive backends.
Alongside it live the column-summary strips tally and proportion, and
summary, which composes all three into a whole-dataframe table. The
shared geometry comes from pavement._geometry, so an SVG spark lines up
box-for-box with the other backends.
Examples:
>>> import pavement.svg as psvg
>>> markup = psvg.spark([1, 2, 3, 4, 5]) # an <svg>...</svg> string
>>> psvg.spark(values, color="steelblue", path="spark.svg")
Summary
¶
The result of summary: an HTML table that renders inline in Jupyter.
Showing it in a notebook — or any tool honoring _repr_html_ — displays
the table; str() returns the same HTML fragment, for embedding
elsewhere. (summary's path= writes a standalone document to disk.)
Source code in src/pavement/svg.py
spark
¶
spark(
data: Iterable[float],
weights: Sequence[float] | None = None,
bins: int | None = 4,
domain: tuple[float, float] | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "horizontal",
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
proportional_representation: bool = False,
min_representation: float = 0.05,
show_box: bool | None = None,
color: str | None = None,
fill_alpha: float = 0.3,
line_color: str | None = None,
line_width: float = 1.2,
height: str = "1em",
inline: bool = True,
hover: bool = True,
value_format: ValueFormat | None = None,
tick_hover_limit: int | None = 24,
highlight: bool = True,
_view_width: float | None = None,
class_: str = "pavement-spark",
path: str | None = None,
) -> str
Render a single pavement as a self-contained inline SVG sparkline.
Returns an <svg>...</svg> string with no external dependencies —
paste it into any HTML and it renders, scaling to the surrounding
text. Like pavement.matplotlib.spark it draws exactly one
distribution (a 1D sequence of values) edge to edge with no axes, and
defaults to 'horizontal' so the value axis runs left-to-right.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values to summarize as a single pavement row. Missing values
( |
required |
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
bins
|
int or None
|
Number of equal-mass bins. None shows all the data instead of
binning it (see |
4
|
domain
|
(float, float) or None
|
Explicit |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'horizontal' runs values left-to-right, the natural fit for an inline strip. |
'vertical'
|
width
|
float
|
Box thickness across the row. As with |
0.6
|
tassel_extent
|
float
|
How far tassel marks reach beyond the box at repeated values. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
proportional_representation
|
bool
|
Turn a rug into a frequency rug: scale each value line's length to
how often that value occurs, so the most common value's line spans the
full box and the rest reach proportionally less (a value seen half as
often draws a line half as long). The lines sit on a shared baseline —
the bottom edge for a horizontal rug, the left edge for a vertical one —
and grow toward the far edge, like little bars. Only meaningful for a
rug, so it
requires |
False
|
min_representation
|
float
|
Floor on a value line's length under proportional_representation, as
a fraction of the full box (so |
0.05
|
show_box
|
bool or None
|
Whether (and how) to draw the long box edges (the borders parallel
to the value axis). None (the default) draws them for a binned spark
and omits them for a rug ( |
None
|
color
|
str
|
Any CSS color. Tints the lines and fills each bin translucently
(see fill_alpha). Defaults to no fill and |
None
|
fill_alpha
|
float
|
Opacity of the per-bin fill drawn when color is given. |
0.3
|
line_color
|
str
|
Color for the box and ticks. Overrides color for the lines;
defaults to color if given, else |
None
|
line_width
|
float
|
Stroke width in pixels. Held constant as the spark scales
( |
1.2
|
height
|
str
|
CSS height baked onto the root when inline is True. |
'1em'
|
inline
|
bool
|
If True, set |
True
|
hover
|
bool
|
If True, add native |
True
|
value_format
|
callable
|
Function mapping a value to its tooltip display string, e.g.
|
None
|
tick_hover_limit
|
int or None
|
Cap on how many ticks (distinct values) get their own per-value
tooltip. At or below it, each tick is individually hoverable; a
denser spark — typically a large rug — falls back to just the
summary tooltip, since hundreds of overlapping hit-areas are both
unhelpful and heavy. None lifts the cap (hover every value,
however many); 0 disables per-tick hover entirely. Binned sparks
have only |
24
|
highlight
|
bool
|
If True, add a scoped |
True
|
class_
|
str
|
CSS class on the root |
'pavement-spark'
|
path
|
str
|
If given, also write the markup here. A |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The |
See Also
pavement.matplotlib.spark : The raster (PNG) counterpart, for print. pavement_stats : Compute the quantile values a spark draws.
Source code in src/pavement/svg.py
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 | |
proportion
¶
proportion(
data: Iterable[object],
orientation: Literal[
"vertical", "horizontal"
] = "horizontal",
colors: Sequence[str] = _PROP_COLORS,
other_color: str = _PROP_OTHER,
max_boxes: int = 12,
min_box: float = 3.0,
catchall_tolerance: float = 0.1,
value_crop: int | None = 128,
line_color: str | None = None,
line_width: float = 1.0,
height: str = "1em",
inline: bool = True,
hover: bool = True,
highlight: bool = True,
class_: str = "pavement-proportion",
path: str | None = None,
) -> str
Render a column's value counts as a self-contained inline SVG strip.
A companion to tally in the same borderless form factor, visualizing a
column's value distribution the way pandas value_counts() reports it.
One box per value, left to right in descending frequency, each sized in
proportion to how often that value occurs. It fills the gap a pavement
spark leaves for categorical columns, which have no numeric distribution
to draw. Missing values are dropped (see proportion_stats).
High-cardinality columns are kept legible: at most max_boxes values get their own box, and the rest are lumped into a single catch-all box on the right. The cutoff comes sooner than max_boxes if a long tail of tiny boxes would otherwise squeeze the catch-all into a misleading width (see catchall_tolerance). Boxes never fall below min_box, so even a rare value stays visible and hoverable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable
|
The column's values, of any type (see |
required |
orientation
|
('vertical', 'horizontal')
|
Box layout. 'horizontal' runs the boxes left-to-right (most common first); 'vertical' stacks them top-to-bottom in the same order. |
'vertical'
|
colors
|
sequence of str
|
CSS colors cycled across the value boxes (so adjacent boxes differ). |
a dark/light blue pair
|
other_color
|
str
|
CSS color of the catch-all box, when present. |
_PROP_OTHER
|
max_boxes
|
int
|
Most values to draw individually before lumping the rest into the catch-all. |
12
|
min_box
|
float
|
Smallest on-screen length of any box, in viewBox units (the strip is
140 long). Keeps a rare value visible and hoverable; the shortfall is
taken proportionally from the larger boxes (see |
3.0
|
catchall_tolerance
|
float
|
How far the catch-all's drawn width may stray from its true proportion, as a fraction, before the individual-box cutoff is moved earlier (lumping more into the catch-all). Smaller is stricter. |
0.1
|
value_crop
|
int or None
|
Cap on a value's length in its tooltip; longer values are truncated with an ellipsis. None disables cropping. |
128
|
line_color
|
str or None
|
Optional hairline outlining each box; None (the default) leaves the
boxes borderless, separated by their fills, like |
None
|
line_width
|
float
|
Outline stroke width in pixels (only when line_color is given). |
1.0
|
height
|
str
|
CSS height baked onto the root when inline is True. |
'1em'
|
inline
|
bool
|
If True, size the root so the strip drops into running text. |
True
|
hover
|
bool
|
If True, give each box a |
True
|
highlight
|
bool
|
If True, add a scoped |
True
|
class_
|
str
|
CSS class on the root |
'pavement-proportion'
|
path
|
str
|
If given, also write the markup here ( |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data has no non-missing values to summarize. |
See Also
tally : The distinct/duplicate/missing companion strip. pavement.core.proportion_stats : The value counts it draws.
Source code in src/pavement/svg.py
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 | |
tally
¶
tally(
data: Iterable[object],
orientation: Literal[
"vertical", "horizontal"
] = "horizontal",
distinct_color: str = _TALLY_DISTINCT,
repeated_color: str = _TALLY_REPEATED,
missing_color: str = _TALLY_MISSING,
line_color: str | None = None,
line_width: float = 1.0,
min_box: float = 3.0,
fill_ratio: float = 1.0,
height: str = "1em",
inline: bool = True,
hover: bool = True,
highlight: bool = True,
noun: str = "entry",
class_: str = "pavement-tally",
path: str | None = None,
) -> str
Render a column's make-up as a self-contained inline SVG strip.
A companion to spark with the same form factor and footprint, but a
different question. Where a spark summarizes the distribution of a
numeric column, a tally summarizes the column itself: three boxes,
sized in proportion to how many of the column's values are distinct
(leftmost), how many duplicate a value already seen (middle), and
how many are missing (rightmost). It works on a column of any type, and
surfaces exactly what a pavement plot can't — missing values and
distinctness.
By default the three boxes fill the strip edge to edge, since the counts
sum to the total (see pavement.core.tally_stats); a category with no
values draws no box. Each box carries a native <title> tooltip with
its share and count — the lines between boxes do not. Returns an
<svg>...</svg> string with no external dependencies; paste it into
any HTML and it renders, scaling to the surrounding text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable
|
The column's values, of any type (see |
required |
orientation
|
('vertical', 'horizontal')
|
Box layout. 'horizontal' lays the boxes left-to-right (distinct, duplicate, missing); 'vertical' stacks them top-to-bottom in the same order. |
'vertical'
|
distinct_color
|
str
|
Any CSS color for each box ( |
_TALLY_DISTINCT
|
repeated_color
|
str
|
Any CSS color for each box ( |
_TALLY_DISTINCT
|
missing_color
|
str
|
Any CSS color for each box ( |
_TALLY_DISTINCT
|
line_color
|
str or None
|
Color of an optional hairline outlining each box (and so separating
adjacent boxes). The default, None, leaves the boxes borderless,
separated by their fills alone. When given, the outline is held at a
constant width as the strip scales ( |
None
|
line_width
|
float
|
Outline stroke width in pixels (only when line_color is given). |
1.0
|
min_box
|
float
|
Smallest on-screen length a box may have for a category that has any values, in viewBox units (the strip is 140 long, so the default is ~2% of it). Keeps a tiny-but-nonzero slice — a stray missing value among thousands — visible and hoverable instead of collapsing to a hairline; the shortfall is taken proportionally from the larger boxes, and the tooltip still reports the true share and count. 0 makes the boxes purely proportional. A category with no values still draws no box. |
3.0
|
fill_ratio
|
float
|
Fraction of the strip's span that the boxes occupy, in [0, 1]. At
1.0 (default) the boxes fill edge to edge. Values below 1.0 leave
the right (or bottom, when vertical) portion of the strip empty —
transparent, with no box drawn. Used by |
1.0
|
height
|
str
|
CSS height baked onto the root when inline is True, so the strip tracks the font size; width follows the aspect. |
'1em'
|
inline
|
bool
|
If True, set |
True
|
hover
|
bool
|
If True, give each box a |
True
|
highlight
|
bool
|
If True, add a scoped |
True
|
noun
|
str
|
Singular noun for what each entry is, used in the tooltips and the
|
'entry'
|
class_
|
str
|
CSS class on the root |
'pavement-tally'
|
path
|
str
|
If given, also write the markup here. A |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty (no values to summarize). |
See Also
spark : The distribution sparkline this strip accompanies. pavement.core.tally_stats : The backend-agnostic counts it draws.
Source code in src/pavement/svg.py
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 | |
summary
¶
summary(
data: Any,
color: str = _TALLY_DISTINCT,
height: str = "1.6em",
hover: bool = True,
highlight: bool = True,
draggable: bool = True,
min_fill: float = 0.1,
pebbles: bool = False,
shared_bounds: bool | None = None,
narrow_value_cols: bool | None = None,
labels: Sequence[Any] | None = None,
class_: str = "pavement-summary",
path: str | None = None,
) -> Summary
Summarize a dataframe, Series, or sequence as one inline HTML table.
The compact, at-a-glance view to reach for when data first lands. It pairs
the column-summary strips of this module into a borderless, headerless
table — one row per column, each showing its tally (how much of it is
distinct, duplicate, or missing) beside its distribution. The distribution
is a pavement spark for an ordered column — numbers, Decimal, or
date/datetime (a temporal column is projected onto a time axis, see
_project) — and a proportion strip for a categorical one, so every
column gets a distribution view where a pavement alone would leave the
categorical ones blank. Every box is hoverable for its exact share, value,
and count.
The return value renders itself in Jupyter (via _repr_html_), so
pavement.summary(df) as the last line of a cell shows the table inline.
What data may be:
- A dataframe — a pandas or polars
DataFrame, or a plaindictmapping column name to a sequence of values (handy with neither installed). Renders one row per column, under a top row summarizing the frame as a whole: its label is the shape ("N by M"— columns by rows), its tally treats each whole row as the entity (so "duplicate" means a duplicated row and "missing" a row that is entirely blank), and its distribution cell is empty (a frame has no single distribution). - A ragged dict — a plain
dictwhose columns are not all the same length (so there is no rectangular "N by M" shape). Renders like a groupby instead: the header shows"N labels"(the column count) and a tally over every value pooled across all columns — the only full-width strip — and each column's tally is scaled to its share of that pooled total (see min_fill). A realDataFrame, always rectangular, never takes this path. - A pandas DataFrameGroupBy — e.g.
df.groupby("team"). Renders one row per group under a top row showing the group and column counts; each row's tally treats whole rows as the entity (same as the plain DataFrame header), so "duplicate" means a duplicated row within that group. Distribution cells are empty (no single column to show). - A pandas SeriesGroupBy — e.g.
df["score"].groupby(df["team"]). Renders one row per group, under a top row showing the series name and group count; the top row's tally and distribution cover all values across every group, giving a global view above the per-group breakdown. Multi-key groupby (grouped by several columns) labels each group with its key components joined by/. - A Series or 1D sequence — a pandas
Series, a list, a numpy array, etc. Renders a single row. A bare sequence has no accessible name, so where a column name would go it shows the entry count instead (e.g."1,234 entries"— "entries", not "values", since the count includes any missing ones).
A pavement column's resolution adapts to its total value count: a rug (every value shown, each hoverable) up to 24, then equal-mass bins — 4 bins up to 96 values, 8 bins up to 256, then 16 — so a small column reads value-by-value and a large one as a smooth shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame, DataFrameGroupBy, SeriesGroupBy, dict, Series, or sequence
|
The thing to summarize (see above). |
required |
color
|
str
|
CSS color tinting the numeric distribution sparks, so they match the tally's "distinct" box. The categorical proportion strips keep their own alternating palette. |
the tally's dark blue
|
height
|
str
|
CSS height of every strip. They share one aspect ratio, so a common height makes the tally and distribution columns line up. |
'1.6em'
|
hover
|
bool
|
Whether the strips carry their native |
True
|
highlight
|
bool
|
Whether the strips brighten the box under the cursor (scoped CSS). |
True
|
draggable
|
bool
|
If True, make the column rows drag-and-drop re-orderable, to rearrange
them (e.g. to compare columns side by side). A small grip handle appears
at the left of each column name and is the only draggable target, so the
rest of each row keeps its normal cursor and stays text-selectable. Adds
a small, self-contained |
True
|
min_fill
|
float
|
When groups or columns have different row counts (a groupby or a
ragged dict with unequal-length values), each tally strip is scaled so
its visible width is proportional to its row count. The reference is the
total number of entries — pooled across every group, or every column
of a ragged dict — so each strip reads on the same scale as the pooled
header row, which, covering every entry, is the only full-width strip.
min_fill is the floor: even the smallest tally strip uses at least
this fraction of the full strip width, so it stays visible. |
0.1
|
pebbles
|
bool
|
Treat data as a label-to-value mapping and lay it out like a
SeriesGroupBy: a header row pooling every value into one full
distribution, then one row per label showing just its single value as a
lone pebble on the shared axis. The intended input is a labeled 1D
result — most often a pandas |
False
|
shared_bounds
|
bool or None
|
Whether to place all distribution strips on a single shared value axis, so their positions can be compared directly. When True, the global min and max across all groups (or all columns, for a dict) are used as the axis endpoints for every numeric distribution strip; a group whose values occupy only part of the global range shows data in the corresponding portion of the strip, with transparent empty space elsewhere. None (the default) auto-detects: True for groupby inputs (where comparing groups on a common axis is usually the point), False for plain DataFrames and dicts (where columns often have different units or scales). Has no effect on categorical proportion strips. By default it also drives narrow_value_cols (a shared axis usually wants the wider distribution), but that layout is separately controllable — see below. |
None
|
narrow_value_cols
|
bool or None
|
Whether to halve the two value (extent) columns flanking the
distribution and give that width to the distribution column, so the
pavements have more room to show where each row's data falls. The
overall table width is unchanged. |
None
|
labels
|
sequence
|
Which columns (or groups, for a groupby) to show and in what order,
overriding the default order from the data. Each entry must match a
column name (for a DataFrame or dict) or a group-key string (for a
groupby). Raises |
None
|
class_
|
str
|
CSS class on the |
'pavement-summary'
|
path
|
str
|
If given, also write the markup here. A |
None
|
Returns:
| Type | Description |
|---|---|
Summary
|
An object that renders the table inline in Jupyter and whose |
See Also
tally : The distinct/duplicate/missing strip in each row. proportion : The categorical distribution strip. spark : The numeric distribution sparkline.
Source code in src/pavement/svg.py
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 | |
Interactive — Plotly (pavement.plotly)¶
plotly
¶
Interactive pavement plots for Plotly.
The pavement.matplotlib renderer draws static matplotlib artists and
the pavement.holoviews module builds backend-agnostic HoloViews
elements. This module targets Plotly directly, so it speaks Plotly's own
vocabulary — plotly.graph_objects traces, plotly.subplots grids — and
slots into a Plotly workflow with native hover, pan, zoom, and legends.
A pavement is a richer drop-in for a rug plot: where a rug draws one tick
per data point, a pavement bins the data into equal-mass quantile boxes
(or, with bins=None, falls back to a tick per point — a literal rug).
The headline use is the same place rugs show up most: as marginals on a
scatter, like Plotly's own marginal_x / marginal_y rugs
(https://plotly.com/python/marginal-plots/). with_marginals adjoins
pavement marginals to a scatter figure in one call.
Each pavement row is built from plain ~plotly.graph_objects.Scatter
traces — no figure-level shapes — so a row drops into any subplot cell
with row=/col= and carries its own hover. A row is:
- one borderless filled rectangle per equal-mass bin, each its own trace
with
hoveron='fills'so hovering anywhere inside the box shows that bin's value range, percentile band, and the share of values inside it; - a single line trace for the quantile ticks and box edges (with tassels where a value repeats, so every line is drawn once); and
- an invisible marker at each quantile tick, carrying that tick's value, percentile, and the share of values on it — the rug-style read.
Plotly hovers filled areas and markers but not lines, so the line trace is purely visual and the two hover layers (box fills, tick markers) carry the text. Hover reads the same as the other backends: the box hover is a value range, percentile band, and value share; the tick hover a single value, percentile, and share (both led by the row's name when it has one). Every value is counted in exactly one bin (strictly inside) or tick (exactly on it).
The functions mirror the rest of the package:
pavement_tracesbuilds one row's traces (the low-level piece).plotbuilds a whole~plotly.graph_objects.Figure, accepting a single dataset, a wide list of datasets, or tidy data plus categories — the counterpart ofpavement.matplotlib.plotandpavement.holoviews.plot.add_pavementadds those rows to an existing figure (optionally into a subplot cell), the building block the other two share.with_marginalsbuilds a scatter-with-marginals joint plot.
Examples:
>>> import pavement.plotly as ppl
>>> ppl.plot([1, 2, 3, 4, 5]).show()
>>> ppl.plot(values, categories=labels).show()
pavement_traces
¶
pavement_traces(
data: Iterable[float],
bins: int | None = 4,
weights: Sequence[float] | None = None,
position: float = 1,
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
color: str | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
name: str | None = None,
hover: bool = True,
value_format: ValueFormat | None = None,
show_legend: bool = False,
) -> list[Scatter]
Build the Plotly traces for a single pavement row.
The low-level piece the rest of the module is built on: it computes
one row's quantile values and returns the ~plotly.graph_objects
traces that draw it, ready to add_trace (optionally into a
subplot cell). Use plot or add_pavement for the usual
single/wide/tidy entry points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values to summarize. |
required |
bins
|
int or None
|
Number of equal-mass bins, or None to show every data point (a
rug). Passed to |
4
|
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
position
|
float
|
Center of the row on the axis perpendicular to the value axis. |
1
|
width
|
float
|
Thickness of the row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box at repeated values. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw the two long box edges. None (the default) draws
them when binned and omits them for a rug ( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'vertical' puts values on the y-axis; 'horizontal' puts them on the x-axis. |
'vertical'
|
color
|
str
|
Color of the lines and (translucent) fill. Any hex, named, or
|
None
|
fill_alpha
|
float
|
Opacity of the bin fills. The ticks and box are drawn opaque. Set to 0 to omit the fill entirely. |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
name
|
str
|
Legend/hover name for the row (e.g. its category). |
None
|
hover
|
bool
|
Whether to enable hover: |
True
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
show_legend
|
bool
|
Whether the row contributes a legend entry (one per row, on its first bin or, if there is no fill, its lines). |
False
|
Returns:
| Type | Description |
|---|---|
list of plotly.graph_objects.Scatter
|
One trace per bin fill, then the line trace, then (if hover) the
tick-marker trace — all sharing a |
See Also
plot : Build a whole figure from one or more datasets. add_pavement : Add rows to an existing figure. pavement.pavement_stats : The underlying quantile computation.
Source code in src/pavement/plotly.py
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
add_pavement
¶
add_pavement(
fig: Figure,
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
hover: bool = True,
value_format: ValueFormat | None = None,
show_legend: bool = True,
row: int | None = None,
col: int | None = None,
) -> Figure
Add one or more pavement rows to an existing figure.
The building block plot and with_marginals share: it accepts
the same single/wide/tidy input shapes as pavement.matplotlib.plot, builds the
traces for each row, and adds them to fig — into a specific subplot
cell when row/col are given. The figure is mutated and returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fig
|
Figure
|
The figure to add to. Mutated in place. |
required |
data
|
sequence of float, or sequence of iterables of float
|
The values to plot; shape selects the mode, as in
|
required |
weights
|
sequence
|
Positive weights, matching the shape of data. |
None
|
positions
|
sequence of float
|
Position of each row on the axis perpendicular to the value axis.
Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data (tidy/long form). If given, data is split by category. |
None
|
labels
|
sequence
|
One label per row, used as the legend/hover name. In tidy form, also selects which categories to include and their order. |
None
|
bins
|
int, None, or sequence
|
Equal-mass bins per row; None shows all the data (a rug). A scalar
applies to every row; a sequence sets each and may mix None with
integers. See |
4
|
widths
|
float or sequence of float
|
Thickness of each row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges. None (the default)
draws them for a binned row and omits them for a rug
( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. |
'vertical'
|
color
|
str or sequence of str
|
Per-row color(s). A single color applies to every row; a sequence sets each and must match the number of rows. Defaults to Plotly's qualitative color cycle. |
None
|
fill_alpha
|
float
|
Opacity of the bin fills (0 omits them). |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
hover
|
bool
|
Whether to add the invisible hover layer to each row. |
True
|
value_format
|
callable
|
Function mapping a value to its hover display string (e.g.
|
None
|
show_legend
|
bool
|
Whether multi-row plots contribute a legend entry per row. A single anonymous row never does. |
True
|
row
|
int
|
Subplot cell to add the traces to, for a figure built with
|
None
|
col
|
int
|
Subplot cell to add the traces to, for a figure built with
|
None
|
Returns:
| Type | Description |
|---|---|
Figure
|
fig, with the rows added. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color, or
labels is a sequence of the wrong length; or for any reason
raised by |
See Also
plot : Create a new figure (calls this). pavement_traces : Build a single row's traces.
Source code in src/pavement/plotly.py
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | |
plot
¶
plot(
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
value_label: str | None = None,
value_format: ValueFormat | None = None,
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
hover: bool = True,
show_legend: bool = False,
fig: Figure | None = None,
) -> Figure
Build an interactive pavement plot as a Plotly figure.
The Plotly counterpart of pavement.matplotlib.plot and
pavement.holoviews.plot. Accepts the same three input shapes — a
single 1D dataset, a wide sequence of datasets, or tidy data plus
categories — and returns a ~plotly.graph_objects.Figure with the
value axis labelled and the position axis ticked by the row labels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
sequence of float, or sequence of iterables of float
|
The values to plot; shape selects the mode, as in
|
required |
weights
|
sequence
|
Positive weights, matching the shape of data. |
None
|
positions
|
sequence of float
|
Position of each row on the axis perpendicular to the value axis.
Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data (tidy/long form). If given, data is split by category. |
None
|
labels
|
sequence
|
One label per row, used as the legend name and position-axis tick. In tidy form, also selects which categories to include and their order. |
None
|
bins
|
int, None, or sequence
|
Equal-mass bins per row; None shows all the data (a rug). See
|
4
|
widths
|
float or sequence of float
|
Thickness of each row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges. None (the default)
draws them for a binned row and omits them for a rug
( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. |
'vertical'
|
value_label
|
str
|
If given, label the value axis (x for horizontal, y otherwise).
Defaults to |
None
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
color
|
str or sequence of str
|
Per-row color(s). Defaults to Plotly's qualitative color cycle, so a category-split pavement matches a default Plotly Express scatter group for group. |
None
|
fill_alpha
|
float
|
Opacity of the bin fills (0 omits them). |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
hover
|
bool
|
Whether to enable hover (via the invisible marker layer). |
True
|
show_legend
|
bool
|
Whether to show the legend (only relevant with multiple rows). Off by default; pass True to label the rows with a legend. |
False
|
fig
|
Figure
|
Figure to draw into. Defaults to a fresh one. (Passing a subplot
figure here draws into its default cell; for a specific cell, use
|
None
|
Returns:
| Type | Description |
|---|---|
Figure
|
A figure containing the pavement, with axes labelled and ticked. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color, or
labels is a sequence of the wrong length; or for any reason
raised by |
See Also
pavement.matplotlib.plot : The matplotlib equivalent. pavement.holoviews.plot : The HoloViews equivalent. with_marginals : Adjoin pavement marginals to a scatter. add_pavement : The lower-level adder this wraps.
Examples:
>>> import pavement.plotly as ppl
>>> ppl.plot([1, 2, 3, 4, 5]).show()
>>> ppl.plot(values, categories=labels).show()
Source code in src/pavement/plotly.py
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | |
with_marginals
¶
with_marginals(
main: Figure,
x: Sequence[float] | None = None,
y: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
size: float = 0.15,
spacing: float = 0.02,
**kwargs: Any,
) -> Figure
Adjoin pavement marginals to a scatter figure — x on top, y on right.
A pavement-flavored take on Plotly's marginal_x / marginal_y
rugs (https://plotly.com/python/marginal-plots/): pass the figure you
would otherwise show and the marginal data, and get back a joint plot
with the scatter in the main cell and a thin pavement strip on the top
(for x) and the right (for y). The marginals share the scatter's data
axes, so they stay aligned through pan and zoom.
The main figure's traces are moved into a fresh subplot grid, so main should be a finished scatter (any styling on its traces is preserved). With categories, each marginal is split by category and colored to match the scatter group for group — colors are read off main's traces by name, so a Plotly Express colored scatter and its marginals share one scheme for free.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
main
|
Figure
|
The central scatter figure. Its traces are re-added to the joint plot's main cell. |
required |
x
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split these are the per-point values in tidy form, parallel to categories. |
None
|
y
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split these are the per-point values in tidy form, parallel to categories. |
None
|
categories
|
sequence
|
Category label per point, parallel to x and y. Splits each
marginal by category, as in |
None
|
size
|
float
|
Thickness of each marginal strip, as a fraction of the figure. |
0.15
|
spacing
|
float
|
Gap between the marginal strips and the main cell, as a fraction of the figure. |
0.02
|
**kwargs
|
Any
|
Forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
Figure
|
A new figure: the scatter with the requested marginals adjoined. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither x nor y is given, or if orientation, color, or show_legend is passed in kwargs (they are managed here). |
See Also
plot : Builds the marginal rows; call it for a standalone plot.
Examples:
>>> import plotly.express as px
>>> import pavement.plotly as ppl
>>> df = px.data.iris()
>>> fig = px.scatter(df, x="sepal_width", y="sepal_length",
... color="species")
>>> ppl.with_marginals(fig, x=df.sepal_width, y=df.sepal_length,
... categories=df.species).show()
Source code in src/pavement/plotly.py
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | |
Interactive — Bokeh (pavement.bokeh)¶
bokeh
¶
Interactive pavement plots for Bokeh.
The matplotlib renderer in the top-level package draws static artists, the
pavement.holoviews module builds backend-agnostic HoloViews elements, and
pavement.plotly targets Plotly directly. This module targets Bokeh in the
same spirit: it speaks Bokeh's own vocabulary — bokeh.plotting.figure,
glyphs backed by ~bokeh.models.ColumnDataSource, a ~bokeh.models.HoverTool
and an interactive ~bokeh.models.Legend — and slots into a Bokeh workflow
with native hover, pan, zoom, and a clickable legend.
A pavement is a richer drop-in for a rug plot: where a rug draws one tick per
data point, a pavement bins the data into equal-mass quantile boxes (or, with
bins=None, falls back to a tick per point — a literal rug). The headline
use is the same place rugs show up most: as marginals on a scatter.
with_marginals arranges a scatter with pavement marginals on the top and
right, with their ranges linked to the scatter's, in one call.
Each pavement row is drawn with plain Bokeh glyphs, so it carries its own hover and drops onto any figure:
- one borderless filled
quad <bokeh.plotting.figure.quad>per equal-mass bin, hovering its value range, percentile band, and the share of values inside it; - a
segment <bokeh.plotting.figure.segment>of quantile ticks (reaching past the box into a tassel where a value repeats, so every line is drawn once), each hovering its value, percentile, and the share of values on it — the rug-style read; and - a
segment <bokeh.plotting.figure.segment>of the two box edges, purely visual, sharing the ticks' style.
Hover reads the same as the other backends: the box hover is a value range, percentile band, and value share; the tick hover a single value, percentile, and share (both led by the row's name when it has one). Every value is counted in exactly one bin (strictly inside) or tick (exactly on it). Unlike Plotly's figure-level shapes, Bokeh glyphs hover directly, so no invisible marker layer is needed.
The functions mirror the rest of the package:
pavement_glyphsadds one row's glyphs to a figure (the low-level piece).add_pavementadds one or more rows — accepting a single dataset, a wide list of datasets, or tidy data plus categories — and wires up the shared hover and legend.plotbuilds a whole~bokeh.plotting.figure, the counterpart ofpavement.matplotlib.plot,pavement.holoviews.plot, andpavement.plotly.plot.with_marginalsbuilds a scatter-with-marginals joint plot.
Examples:
>>> import pavement.bokeh as pbk
>>> from bokeh.plotting import show
>>> show(pbk.plot([1, 2, 3, 4, 5]))
>>> show(pbk.plot(values, categories=labels))
pavement_glyphs
¶
pavement_glyphs(
fig: figure,
data: Iterable[float],
bins: int | None = 4,
weights: Sequence[float] | None = None,
position: float = 1,
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
color: str | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
name: Hashable | None = None,
value_format: ValueFormat | None = None,
) -> dict[str, GlyphRenderer]
Add a single pavement row's glyphs to a Bokeh figure.
The low-level piece the rest of the module is built on: it computes one
row's quantile values and draws them onto fig as Bokeh glyphs,
returning the renderers. It draws only the glyphs — the shared hover
tool and legend are figure-level concerns wired up by add_pavement, so
reach for plot or add_pavement for the usual single/wide/tidy
entry points and interactivity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fig
|
figure
|
The figure to draw on. Mutated in place. |
required |
data
|
iterable of float
|
The values to summarize. |
required |
bins
|
int or None
|
Number of equal-mass bins, or None to show every data point (a rug).
Passed to |
4
|
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
position
|
float
|
Center of the row on the axis perpendicular to the value axis. |
1
|
width
|
float
|
Thickness of the row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box at repeated values. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw the two long box edges. None (the default) draws
them when binned and omits them for a rug ( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'vertical' puts values on the y-axis; 'horizontal' puts them on the x-axis. |
'vertical'
|
color
|
str
|
Color of the lines and (translucent) fill. Defaults to the first
Bokeh |
None
|
fill_alpha
|
float
|
Opacity of the bin fills. The ticks and box are drawn opaque. Set to 0 to omit the fills entirely. |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
name
|
hashable
|
Row name (e.g. its category). Carried as a |
None
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Maps component name to the
|
See Also
add_pavement : Add one or more rows and wire up hover and the legend. plot : Build a whole figure from one or more datasets. pavement.pavement_stats : The underlying quantile computation.
Source code in src/pavement/bokeh.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | |
add_pavement
¶
add_pavement(
fig: figure,
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
hover: bool = True,
value_format: ValueFormat | None = None,
show_legend: bool = True,
) -> figure
Add one or more pavement rows to an existing figure.
The building block plot and with_marginals share: it accepts the
same single/wide/tidy input shapes as pavement.matplotlib.plot, draws each row's
glyphs, and wires up the shared interactivity — one ~bokeh.models.HoverTool
over all the rows' bins and ticks, and, for multiple rows, a clickable
~bokeh.models.Legend (each entry toggles its whole row). The figure is
mutated and returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fig
|
figure
|
The figure to add to. Mutated in place. |
required |
data
|
sequence of float, or sequence of iterables of float
|
The values to plot; shape selects the mode, as in |
required |
weights
|
sequence
|
Positive weights, matching the shape of data. |
None
|
positions
|
sequence of float
|
Position of each row on the axis perpendicular to the value axis.
Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data (tidy/long form). If given, data is split by category. |
None
|
labels
|
sequence
|
One label per row, used as the legend/hover name. In tidy form, also selects which categories to include and their order. |
None
|
bins
|
int, None, or sequence
|
Equal-mass bins per row; None shows all the data (a rug). A scalar
applies to every row; a sequence sets each and may mix None with
integers. See |
4
|
widths
|
float or sequence of float
|
Thickness of each row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges. None (the default)
draws them for a binned row and omits them for a rug
( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. |
'vertical'
|
color
|
str or sequence of str
|
Per-row color(s). A single color applies to every row; a sequence
sets each and must match the number of rows. Defaults to Bokeh's
|
None
|
fill_alpha
|
float
|
Opacity of the bin fills (0 omits them). |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
hover
|
bool
|
Whether to add a hover tool over the rows' bins and ticks. |
True
|
value_format
|
callable
|
Function mapping a value to its hover display string (e.g.
|
None
|
show_legend
|
bool
|
Whether multi-row plots get a legend (one clickable entry per row). A single anonymous row never does. |
True
|
Returns:
| Type | Description |
|---|---|
figure
|
fig, with the rows added. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color, or
labels is a sequence of the wrong length; or for any reason raised
by |
See Also
plot : Create a new figure (calls this). pavement_glyphs : Draw a single row's glyphs.
Source code in src/pavement/bokeh.py
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | |
plot
¶
plot(
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
value_label: str | None = None,
value_format: ValueFormat | None = None,
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
line_width: float = 1.0,
hover: bool = True,
show_legend: bool = False,
fig: figure | None = None,
**figure_kwargs: Any,
) -> figure
Build an interactive pavement plot as a Bokeh figure.
The Bokeh counterpart of pavement.matplotlib.plot, pavement.holoviews.plot,
and pavement.plotly.plot. Accepts the same three input shapes — a
single 1D dataset, a wide sequence of datasets, or tidy data plus
categories — and returns a ~bokeh.plotting.figure with the value axis
labelled and the position axis ticked by the row labels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
sequence of float, or sequence of iterables of float
|
The values to plot; shape selects the mode, as in |
required |
weights
|
sequence
|
Positive weights, matching the shape of data. |
None
|
positions
|
sequence of float
|
Position of each row on the axis perpendicular to the value axis.
Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data (tidy/long form). If given, data is split by category. |
None
|
labels
|
sequence
|
One label per row, used as the legend name and position-axis tick. In tidy form, also selects which categories to include and their order. |
None
|
bins
|
int, None, or sequence
|
Equal-mass bins per row; None shows all the data (a rug). See
|
4
|
widths
|
float or sequence of float
|
Thickness of each row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges. None (the default)
draws them for a binned row and omits them for a rug
( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. |
'vertical'
|
value_label
|
str
|
If given, label the value axis (x for horizontal, y otherwise).
Defaults to |
None
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
color
|
str or sequence of str
|
Per-row color(s). Defaults to Bokeh's |
None
|
fill_alpha
|
float
|
Opacity of the bin fills (0 omits them). |
0.3
|
line_width
|
float
|
Width of the tick and box-edge lines. |
1.0
|
hover
|
bool
|
Whether to enable hover. |
True
|
show_legend
|
bool
|
Whether to show the legend (only relevant with multiple rows). Off by default; pass True to label the rows with a legend. |
False
|
fig
|
figure
|
Figure to draw into. Defaults to a fresh one built from figure_kwargs. |
None
|
**figure_kwargs
|
Any
|
Forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
figure
|
A figure containing the pavement, with axes labelled and ticked. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color, or
labels is a sequence of the wrong length; or for any reason raised
by |
See Also
pavement.matplotlib.plot : The matplotlib equivalent. pavement.plotly.plot : The Plotly equivalent. with_marginals : Arrange a scatter with pavement marginals. add_pavement : The lower-level adder this wraps.
Examples:
>>> import pavement.bokeh as pbk
>>> from bokeh.plotting import show
>>> show(pbk.plot([1, 2, 3, 4, 5]))
>>> show(pbk.plot(values, categories=labels))
Source code in src/pavement/bokeh.py
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | |
with_marginals
¶
with_marginals(
main: figure,
x: Sequence[float] | None = None,
y: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
size: int = 120,
**kwargs: Any,
) -> Any
Arrange a scatter with pavement marginals — x on top, y on the right.
A pavement-flavored take on a joint plot: pass the scatter figure you
would otherwise show and the marginal data, and get back a
~bokeh.models.GridPlot with the scatter in the main cell and a thin
pavement strip on the top (for x) and the right (for y). The marginals'
ranges are linked to the scatter's, so they stay aligned through pan and
zoom.
With categories, each marginal is split by category and colored to
match the scatter group for group — colors are read off main's
renderers by name (so set name= on the scatter's per-category
renderers), and any label the scatter doesn't color falls back to
Bokeh's default palette.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
main
|
figure
|
The central scatter figure. Reused as the main cell; its ranges are shared with the marginals. |
required |
x
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split these are the per-point values in tidy form, parallel to categories. |
None
|
y
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split these are the per-point values in tidy form, parallel to categories. |
None
|
categories
|
sequence
|
Category label per point, parallel to x and y. Splits each
marginal by category, as in |
None
|
size
|
int
|
Thickness of each marginal strip in pixels. |
120
|
**kwargs
|
Any
|
Forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
GridPlot
|
A grid laying out the scatter with the requested marginals adjoined. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither x nor y is given, or if orientation, color, or show_legend is passed in kwargs (they are managed here). |
See Also
plot : Builds the marginal rows; call it for a standalone plot.
Examples:
>>> import pavement.bokeh as pbk
>>> from bokeh.plotting import figure, show
>>> p = figure()
>>> p.scatter(xs, ys)
>>> show(pbk.with_marginals(p, x=xs, y=ys))
Source code in src/pavement/bokeh.py
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 | |
Interactive — HoloViews (pavement.holoviews)¶
holoviews
¶
Interactive pavement plots for HoloViews.
The matplotlib renderer in the top-level package draws static artists.
This module builds the same pavement geometry as HoloViews elements, so
it renders through any HoloViews backend — bokeh and plotly for
interactivity (hover, pan, zoom, legends), or matplotlib for a
static image. Backend-specific styling (fill colors, the hover tool) is
resolved for whichever backend is active when the plot is built, so
select it with hv.extension(...) first, as usual.
A pavement row is built from three overlaid components: a borderless
holoviews.Rectangles of the equal-mass bins (a hover target carrying
each bin's value range, percentile band, and value share), and two holoviews.Segments
— the quantile ticks and the box edges. Keeping the lines separate from
the fill means the ticks and box share one consistent style; a repeated
quantile value (data piled up) simply extends its own tick into a
tassel, so every line is drawn exactly once. The ticks carry their own
hover, like a rug plot's.
The headline function is plot, which mirrors the matplotlib backend's
pavement.matplotlib.plot: it accepts a single dataset, a wide list of
datasets, or tidy data plus categories, and returns a HoloViews
object. Because
the result is a plain HoloViews element, framework features compose on
top of it — overlay it on a scatter, adjoin it as a marginal with the
<< operator, or split it by category into a colored, legended
NdOverlay. To adjoin pavements as joint-plot marginals, reach for
with_marginals, which places an x-marginal on top and a y-marginal on
the right with the correct orientation handled for you.
Examples:
>>> import holoviews as hv
>>> import pavement.holoviews as phv
>>> hv.extension('bokeh')
>>> phv.plot([1, 2, 3, 4, 5])
>>> phv.plot(values, categories=labels)
pavement_elements
¶
pavement_elements(
data: Iterable[float],
bins: int | None = 4,
weights: Sequence[float] | None = None,
position: float = 1,
width: float = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
group: Hashable | None = None,
value_format: ValueFormat | None = None,
) -> dict[str, Any]
Build the raw HoloViews elements for a single pavement row.
The lower-level companion to plot: it computes one row's quantile
values and returns the unstyled component elements, leaving styling,
overlaying, and axis labelling to the caller. plot wraps this.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
iterable of float
|
The values to summarize. |
required |
bins
|
int or None
|
Number of equal-mass bins, or None to show every data point (a
rug). Passed to |
4
|
weights
|
sequence of float
|
Positive weights parallel to data. |
None
|
position
|
float
|
Center of the row on the axis perpendicular to the value axis. |
1
|
width
|
float
|
Thickness of the row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box at repeated values. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw the two long box edges. None (the default) draws
them when binned and omits them for a rug ( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. 'vertical' puts values on the y-axis; 'horizontal' puts them on the x-axis. |
'vertical'
|
group
|
hashable
|
If given, the row name; it leads each fill's and tick's composed
|
None
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Maps component name to the unstyled HoloViews element:
|
See Also
plot : The headline, multi-row function built on this. pavement.pavement_stats : The underlying quantile computation.
Source code in src/pavement/holoviews.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | |
plot
¶
plot(
data: Sequence[float] | Sequence[Iterable[float]],
weights: Sequence[float]
| Sequence[Sequence[float]]
| None = None,
positions: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
labels: Sequence[Hashable] | None = None,
bins: int | None | Sequence[int | None] = 4,
widths: float | Sequence[float] = 0.6,
tassel_extent: float = 0.05,
show_tassels: bool = False,
show_box: bool | None = None,
orientation: Literal[
"vertical", "horizontal"
] = "vertical",
value_label: str | None = None,
value_format: ValueFormat | None = None,
color: str | Sequence[str] | None = None,
fill_alpha: float = 0.3,
hover: bool = True,
show_legend: bool = False,
transpose_labels: bool = False,
) -> Any
Build an interactive pavement plot as a HoloViews object.
The HoloViews counterpart of pavement.matplotlib.plot. Accepts the
same three input shapes — a single 1D dataset, a wide sequence of
datasets, or tidy data plus categories — and returns a HoloViews
object that renders through any backend.
A single dataset returns a holoviews.Overlay (the bins, plus any
tassels). Multiple rows return a holoviews.NdOverlay keyed by
labels, which gives a legend and a consistent per-row color cycle;
in tidy form this is the "split by category" case. Either result is
a plain HoloViews object, so it composes with the framework: overlay
it with *, adjoin it as a marginal with <<, or restyle it
with .opts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
sequence of float, or sequence of iterables of float
|
The values to plot. Shape determines the mode, as in
|
required |
weights
|
sequence
|
Positive weights, matching the shape of data. |
None
|
positions
|
sequence of float
|
Position of each row on the axis perpendicular to the value
axis. Defaults to |
None
|
categories
|
sequence
|
Category label per entry in data (tidy/long form). If given, data is split by category. |
None
|
labels
|
sequence
|
One label per row, used as the legend key and color order. In
tidy form, also selects which categories to include and their
order. Defaults to |
None
|
bins
|
int, None, or sequence
|
Equal-mass bins per row; None shows all the data (a rug). A
scalar applies to every row; a sequence sets each row and may
mix None with integers. See |
4
|
widths
|
float or sequence of float
|
Thickness of each row. |
0.6
|
tassel_extent
|
float
|
How far tassel marks extend beyond the box. |
0.05
|
show_tassels
|
bool
|
Whether to draw tassel marks at repeated quantile values. |
False
|
show_box
|
bool or None
|
Whether to draw each row's two long box edges. None (the default)
draws them for a binned row and omits them for a rug
( |
None
|
orientation
|
('vertical', 'horizontal')
|
Direction of the value axis. |
'vertical'
|
value_label
|
str
|
If given, label the value axis (x for horizontal, y otherwise).
Defaults to |
None
|
value_format
|
callable
|
Function mapping a value to its hover display string, e.g.
|
None
|
color
|
str or sequence of str
|
Per-row color(s). A single color applies to every row; a sequence sets each row and must match the number of rows. Defaults to HoloViews' own color cycle, so a category-split pavement's groups match a default-colored main plot's groups (in the same key order) when used as a marginal. |
None
|
fill_alpha
|
float
|
Opacity of the bin fills. Bin borders (the ticks and box) are drawn opaque. |
0.3
|
hover
|
bool
|
Whether to enable a hover tool (bokeh only; plotly hovers by default, matplotlib has none). |
True
|
show_legend
|
bool
|
Whether to show the category legend (only relevant with multiple
rows). Off by default; pass True to label the rows with a legend.
Has no effect on matplotlib, which can't build a legend handle for
the bin glyphs. |
False
|
transpose_labels
|
bool
|
Place the value-axis label and the position ticks on the
opposite axes from orientation. Use this only when the plot
will be rendered transposed — as HoloViews' adjoint does for a
right/left marginal, where it swaps the axes but not the tick
labels. |
False
|
Returns:
| Type | Description |
|---|---|
Overlay or NdOverlay
|
An |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is empty; if positions, bins, widths, color,
or labels is given as a sequence of the wrong length; or for
any reason raised by |
See Also
pavement.matplotlib.plot : The matplotlib equivalent. pavement_elements : The single-row element builder this wraps.
Examples:
>>> import holoviews as hv
>>> import pavement.holoviews as phv
>>> hv.extension('bokeh')
>>> phv.plot([1, 2, 3, 4, 5])
Split tidy data by category, then adjoin it as a top marginal::
main = hv.Scatter((x, y))
top = phv.plot(x, categories=group, orientation='horizontal')
layout = main << top # doctest: +SKIP
Source code in src/pavement/holoviews.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | |
with_marginals
¶
with_marginals(
main: Any,
x: Sequence[float] | None = None,
y: Sequence[float] | None = None,
categories: Sequence[Hashable] | None = None,
x_label: str = "x",
y_label: str = "y",
size: int | None = None,
**kwargs: Any,
) -> Any
Adjoin pavement marginals to a plot — x on top, y on the right.
A one-call joint-plot helper that hides the things you would
otherwise have to know to adjoin a pavement with HoloViews' <<
operator: that each marginal must be built with
orientation='horizontal' (HoloViews orients each adjoined slot to
share the main plot's axis), that << fills the right slot before
the top, and how to keep the marginal strips thin. Pass the marginal
data and it places them correctly.
The marginals are drawn as thin strips with their (redundant)
category legends turned off, so they don't crowd the main plot. With
categories, each is split by category; leaving color at its
default (see plot) makes the groups match a default-colored
main plot, so a colored scatter and its marginals share one color
scheme for free.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
main
|
holoviews object
|
The central plot, e.g. a |
required |
x
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split, these are the per-point x and y values in tidy form, parallel to categories. |
None
|
y
|
sequence of float
|
Data for the top (x) and right (y) marginals. Provide either or both; at least one is required. For a category split, these are the per-point x and y values in tidy form, parallel to categories. |
None
|
categories
|
sequence
|
Category label per point, parallel to x and y. Splits each
marginal by category, as in |
None
|
x_label
|
str
|
Value-axis labels for the top and right marginals. |
'x', 'y'
|
y_label
|
str
|
Value-axis labels for the top and right marginals. |
'x', 'y'
|
size
|
int
|
Thickness of each marginal strip in pixels (bokeh/plotly; the matplotlib adjoint sizes its own). Defaults to roughly 40px per category, so multi-group marginals stay legible. Pass a larger value to give crowded categories more room. |
None
|
**kwargs
|
Any
|
Forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
AdjointLayout
|
main with the requested marginals adjoined. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither x nor y is given, or if orientation is passed in kwargs (it is chosen automatically). |
See Also
plot : Builds each marginal; call it directly for finer control.
Examples:
>>> import pavement.holoviews as phv
>>> scatter = hv.NdOverlay(...)
>>> phv.with_marginals(scatter, x=xs, y=ys,
... categories=groups)
Source code in src/pavement/holoviews.py
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 | |
pandas integration (pavement.pandas)¶
Importing this module registers the .pave accessor on pandas DataFrame
and Series.
pandas
¶
Pandas integration: a .pave accessor and an opt-in summary repr.
Importing this module registers a .pave accessor on pandas DataFrame,
Series, SeriesGroupBy, and DataFrameGroupBy (the first two through
pandas' own accessor API; the GroupBy ones via a compatible descriptor, since
pandas exposes no public registration hook for them), putting the pavement
strips a method away::
import pavement.pandas # registers .pave
df.pave() # the whole-frame summary (renders inline)
df.pave.summary() # the same, spelled out
df.pave.spark("price") # a numeric column's pavement sparkline
df.pave.tally("plan") # a column's distinct/duplicate/missing strip
df.pave.proportion("plan") # a column's value-counts strip
s = df["price"]
s.pave() # a Series summarizes as one row
s.pave.spark() # the column helpers take no column name
df["score"].groupby(df["team"]).pave() # one row per group (SeriesGroupBy)
df.groupby("team").pave() # one row per group (DataFrameGroupBy)
A labeled Series — say a groupby aggregate — also gets a .pebbles shortcut
for the one-value-per-label view (s.pave(pebbles=True) spelled shorter)::
df.groupby("team")["score"].mean().pebbles() # one pebble per team
df.pave() and .summary() return the same pavement.summary result (a
Summary, which renders inline in Jupyter). The single-column helpers return
the svg string of the matching pavement.svg glyph, wrapped so it also
renders inline in a notebook while still behaving as the plain string
everywhere else (it is a str subclass).
Optionally make the summary a frame's default notebook display::
pavement.pandas.enable_repr() # every DataFrame/Series previews as a summary
pavement.pandas.disable_repr() # restore pandas' normal display
That one replaces the usual data-table preview (it does not append to it), so it is strictly opt-in. It needs a running IPython/Jupyter; importing the accessor needs only pandas.
This module follows the same pattern as import hvplot.pandas — the
integration activates on import, never on a bare import pavement, so the
core package stays dependency-free.
enable_repr
¶
Make pavement.summary the default inline display of pandas objects.
Registers an IPython HTML formatter so that every DataFrame (and,
unless series is False, every Series) renders as its pavement
summary in the notebook, replacing the usual data-table preview rather
than adding to it. Extra keyword arguments are forwarded to summary
(e.g. height, color). Undo with disable_repr.
Raises RuntimeError if there is no running IPython/Jupyter session.
Source code in src/pavement/pandas.py
polars integration (pavement.polars)¶
Importing this module registers the .pave namespace on polars DataFrame
and Series.
polars
¶
Polars integration: a .pave namespace and an opt-in summary repr.
The polars counterpart of pavement.pandas. Importing this module registers a
.pave namespace on polars DataFrame, Series, and GroupBy
(DataFrame and Series through polars' own namespace API; GroupBy via a
compatible descriptor, since polars exposes no public registration hook for
GroupBy types), putting the pavement strips a method away::
import pavement.polars # registers .pave
df.pave() # the whole-frame summary (renders inline)
df.pave.summary() # the same, spelled out
df.pave.spark("price") # a numeric column's pavement sparkline
df.pave.tally("plan") # a column's distinct/duplicate/missing strip
df.pave.proportion("plan") # a column's value-counts strip
s = df["price"]
s.pave() # a Series summarizes as one row
s.pave.spark() # the column helpers take no column name
df.group_by("team").pave() # one row per group
A polars Series has no index, so the one-value-per-label "pebbles" view comes
from a two-column (labels, values) frame instead (its second column names
the pooled header)::
df.group_by("team").agg(pl.col("score").mean()).pebbles() # one per team
df.pave() / .summary() return the pavement.summary result (a
Summary, which renders inline in Jupyter); the single-column helpers return
the matching pavement.svg glyph's string, wrapped so it also renders
inline (it is a str subclass — see pavement._inline.SVG).
Optionally make the summary a frame's default notebook display::
pavement.polars.enable_repr() # every DataFrame/Series previews as a summary
pavement.polars.disable_repr() # restore polars' normal display
That replaces the usual data-table preview (it does not append), so it is
strictly opt-in, and needs a running IPython/Jupyter. The integration
activates on import pavement.polars only, never on a bare import
pavement, keeping the core dependency-free.
enable_repr
¶
Make pavement.summary the default inline display of polars objects.
Registers an IPython HTML formatter so that every DataFrame (and,
unless series is False, every Series) renders as its pavement
summary in the notebook, replacing polars' usual data-table preview.
Extra keyword arguments are forwarded to summary (e.g. height,
color). Undo with disable_repr.
Raises RuntimeError if there is no running IPython/Jupyter session.