pavement.summary

One call, an at-a-glance picture of a dataframe, Series, or sequence — a tally beside a distribution for every column. Hover any strip for its share, value, and count, or grab a row's grip handle to reorder.

tally: distinct   duplicate   missing

A dataframe

One row per column, under a top row for the frame as a whole: its 507 rows, and a tally that treats each whole row as the entity. Numeric columns get a pavement spark whose resolution adapts to the column — a frequency rug for 24 or fewer values, or for 16 or fewer distinct values (so the discrete rating shows its five levels and their counts as scaled lines rather than equal-mass bins), then 4, 8, or 16 equal-mass bins for larger continuous columns. Dates work too: signup_date is laid out on a time axis (hover for the dates). Durations too: session_duration shows timedeltas on a duration axis (e.g. 1d 02:00). Categorical columns get a proportion strip, and legacy_field shows what an almost-all-missing column looks like.

Show code
import pavement

pavement.summary(df)        # dict of lists, pandas/polars DataFrame, or any mapping
10 by 507
column tally: 500 distinct, 3 duplicate, 4 missing of 507 rowsdistinct 99% (500 of 507 rows) (497 appearing once)duplicate 1% (3 of 507 rows)missing 1% (4 of 507 rows)
user_id
column tally: 500 distinct, 3 duplicate, 4 missing of 507 entriesdistinct 99% (500 of 507 entries) (497 appearing once)duplicate 1% (3 of 507 entries)missing 1% (4 of 507 entries)
100,000
pavement sparkline of 503 values1e+05 to 1e+05 p0 to p6 6% (30 of 503 values)1e+05 to 1e+05 p6 to p12 6% (30 of 503 values)1e+05 to 1e+05 p12 to p19 6% (31 of 503 values)1e+05 to 1e+05 p19 to p25 6% (30 of 503 values)1e+05 to 1e+05 p25 to p31 6% (31 of 503 values)1e+05 to 1e+05 p31 to p38 6% (30 of 503 values)1e+05 to 1e+05 p38 to p44 6% (31 of 503 values)1e+05 to 1e+05 p44 to p50 6% (30 of 503 values)1e+05 to 1e+05 p50 to p56 6% (30 of 503 values)1e+05 to 1e+05 p56 to p62 6% (31 of 503 values)1e+05 to 1e+05 p62 to p69 6% (30 of 503 values)1e+05 to 1e+05 p69 to p75 6% (31 of 503 values)1e+05 to 1e+05 p75 to p81 6% (30 of 503 values)1e+05 to 1e+05 p81 to p88 6% (31 of 503 values)1e+05 to 1e+05 p88 to p94 6% (30 of 503 values)1e+05 to 1e+05 p94 to p100 6% (30 of 503 values)1e+05 p0 <1% (1 of 503 values)1e+05 p6 <1% (1 of 503 values)1e+05 p12 <1% (1 of 503 values)1e+05 p19 <1% (1 of 503 values)1e+05 p25 <1% (1 of 503 values)1e+05 p31 <1% (1 of 503 values)1e+05 p38 <1% (1 of 503 values)1e+05 p44 <1% (1 of 503 values)1e+05 p50 <1% (1 of 503 values)1e+05 p56 <1% (1 of 503 values)1e+05 p62 <1% (1 of 503 values)1e+05 p69 <1% (1 of 503 values)1e+05 p75 <1% (1 of 503 values)1e+05 p81 <1% (1 of 503 values)1e+05 p88 <1% (1 of 503 values)1e+05 p94 <1% (1 of 503 values)1e+05 p100 <1% (1 of 503 values)
100,499
plan
column tally: 3 distinct, 433 duplicate, 71 missing of 507 entriesdistinct 1% (3 of 507 entries) (0 appearing once)duplicate 85% (433 of 507 entries)missing 14% (71 of 507 entries)
free
value proportions of 436 values across 3 distinct valuesfree 49% (214 of 436 values)pro 37% (162 of 436 values)team 14% (60 of 436 values)
team
rating
column tally: 5 distinct, 430 duplicate, 72 missing of 507 entriesdistinct 1% (5 of 507 entries) (0 appearing once)duplicate 85% (430 of 507 entries)missing 14% (72 of 507 entries)
1
pavement sparkline of 435 values1 to 2 0% (0 of 435 values)2 to 3 0% (0 of 435 values)3 to 4 0% (0 of 435 values)4 to 5 0% (0 of 435 values)1 p0 to p20 20% (86 of 435 values)2 p20 to p41 22% (95 of 435 values)3 p42 to p63 22% (94 of 435 values)4 p63 to p85 22% (97 of 435 values)5 p86 to p100 14% (63 of 435 values)
5
age
column tally: 56 distinct, 422 duplicate, 29 missing of 507 entriesdistinct 11% (56 of 507 entries) (5 appearing once)duplicate 83% (422 of 507 entries)missing 6% (29 of 507 entries)
4
pavement sparkline of 478 values4 to 22 p0 to p6 5% (24 of 478 values)22 to 26 p6 to p12 5% (25 of 478 values)26 to 29 p12 to p19 4% (18 of 478 values)29 to 31 p19 to p25 3% (16 of 478 values)31 to 33 p25 to p31 4% (19 of 478 values)33 to 35 p31 to p38 3% (12 of 478 values)35 to 37 p38 to p44 3% (15 of 478 values)37 to 38 0% (0 of 478 values)38 to 40 p50 to p56 4% (20 of 478 values)40 to 42 p56 to p62 3% (13 of 478 values)42 to 44 p62 to p69 3% (15 of 478 values)44 to 46 p69 to p75 3% (14 of 478 values)46 to 49 p75 to p81 5% (23 of 478 values)49 to 52 p81 to p88 4% (17 of 478 values)52 to 55 p88 to p94 4% (21 of 478 values)55 to 70 p94 to p100 5% (23 of 478 values)4 p0 <1% (1 of 478 values)22 p6 2% (9 of 478 values)26 p12 3% (12 of 478 values)29 p19 2% (11 of 478 values)31 p25 2% (10 of 478 values)33 p31 3% (12 of 478 values)35 p38 4% (19 of 478 values)37 p44 4% (17 of 478 values)38 p50 4% (20 of 478 values)40 p56 4% (20 of 478 values)42 p62 3% (15 of 478 values)44 p69 3% (13 of 478 values)46 p75 3% (14 of 478 values)49 p81 2% (11 of 478 values)52 p88 2% (10 of 478 values)55 p94 2% (8 of 478 values)70 p100 <1% (1 of 478 values)
70
signup_date
column tally: 307 distinct, 196 duplicate, 4 missing of 507 entriesdistinct 61% (307 of 507 entries) (201 appearing once)duplicate 39% (196 of 507 entries)missing 1% (4 of 507 entries)
2023-01-01
pavement sparkline of 503 values2023-01-01 to 2023-01-03 p0 to p6 2% (9 of 503 values)2023-01-03 to 2023-01-15 p6 to p12 6% (30 of 503 values)2023-01-15 to 2023-01-28 p12 to p19 5% (27 of 503 values)2023-01-28 to 2023-02-12 p19 to p25 6% (28 of 503 values)2023-02-12 to 2023-03-22 p25 to p31 6% (28 of 503 values)2023-03-22 to 2023-04-25 p31 to p38 6% (28 of 503 values)2023-04-25 to 2023-05-24 p38 to p44 6% (31 of 503 values)2023-05-24 to 2023-07-10 p44 to p50 6% (30 of 503 values)2023-07-10 to 2023-08-24 p50 to p56 6% (29 of 503 values)2023-08-24 to 2023-10-16 p56 to p62 6% (29 of 503 values)2023-10-16 to 2023-12-02 p62 to p69 6% (30 of 503 values)2023-12-02 to 2024-01-17 p69 to p75 6% (28 of 503 values)2024-01-17 to 2024-04-06 p75 to p81 6% (29 of 503 values)2024-04-06 to 2024-07-04 p81 to p88 6% (31 of 503 values)2024-07-04 to 2024-10-09 p88 to p94 6% (29 of 503 values)2024-10-09 to 2024-12-31 p94 to p100 6% (29 of 503 values)2023-01-01 p0 4% (18 of 503 values)2023-01-03 p6 1% (5 of 503 values)2023-01-15 p12 1% (4 of 503 values)2023-01-28 p19 <1% (2 of 503 values)2023-02-12 p25 1% (3 of 503 values)2023-03-22 p31 1% (4 of 503 values)2023-04-25 p38 1% (3 of 503 values)2023-05-24 p44 <1% (1 of 503 values)2023-07-10 p50 <1% (1 of 503 values)2023-08-24 p56 1% (3 of 503 values)2023-10-16 p62 <1% (2 of 503 values)2023-12-02 p69 1% (4 of 503 values)2024-01-17 p75 <1% (2 of 503 values)2024-04-06 p81 <1% (1 of 503 values)2024-07-04 p88 <1% (1 of 503 values)2024-10-09 p94 <1% (2 of 503 values)2024-12-31 p100 <1% (2 of 503 values)
2024-12-31
session_duration
column tally: 463 distinct, 40 duplicate, 4 missing of 507 entriesdistinct 91% (463 of 507 entries) (432 appearing once)duplicate 8% (40 of 507 entries)missing 1% (4 of 507 entries)
00:00:30
pavement sparkline of 503 values00:00:30 to 00:01:30 p0 to p6 4% (21 of 503 values)00:01:30 to 00:04:07 p6 to p12 6% (30 of 503 values)00:04:07 to 00:06:45 p12 to p19 6% (30 of 503 values)00:06:45 to 00:08:58 p19 to p25 6% (30 of 503 values)00:08:58 to 00:11:50 p25 to p31 6% (31 of 503 values)00:11:50 to 00:13:37 p31 to p38 6% (30 of 503 values)00:13:37 to 00:17:31 p38 to p44 6% (31 of 503 values)00:17:31 to 00:21:51 p44 to p50 6% (30 of 503 values)00:21:51 to 00:25:52 p50 to p56 6% (30 of 503 values)00:25:52 to 00:31:03 p56 to p62 6% (31 of 503 values)00:31:03 to 00:35:58 p62 to p69 6% (30 of 503 values)00:35:58 to 00:44:24 p69 to p75 6% (31 of 503 values)00:44:24 to 00:52:30 p75 to p81 6% (30 of 503 values)00:52:30 to 01:05:53 p81 to p88 6% (31 of 503 values)01:05:53 to 01:32:33 p88 to p94 6% (30 of 503 values)01:32:33 to 03:43:07 p94 to p100 6% (30 of 503 values)00:00:30 p0 2% (10 of 503 values)00:01:30 p6 <1% (1 of 503 values)00:04:07 p12 <1% (1 of 503 values)00:06:45 p19 <1% (2 of 503 values)00:08:58 p25 <1% (1 of 503 values)00:11:50 p31 <1% (1 of 503 values)00:13:37 p38 <1% (1 of 503 values)00:17:31 p44 <1% (1 of 503 values)00:21:51 p50 <1% (1 of 503 values)00:25:52 p56 <1% (1 of 503 values)00:31:03 p62 <1% (1 of 503 values)00:35:58 p69 <1% (1 of 503 values)00:44:24 p75 <1% (1 of 503 values)00:52:30 p81 <1% (1 of 503 values)01:05:53 p88 <1% (1 of 503 values)01:32:33 p94 <1% (1 of 503 values)03:43:07 p100 <1% (1 of 503 values)
03:43:07
purchases
column tally: 350 distinct, 153 duplicate, 4 missing of 507 entriesdistinct 69% (350 of 507 entries) (248 appearing once)duplicate 30% (153 of 507 entries)missing 1% (4 of 507 entries)
0
pavement sparkline of 503 values0 to 2 p0 to p6 6% (30 of 503 values)2 to 4 p6 to p12 6% (29 of 503 values)4 to 6.2 p12 to p19 6% (31 of 503 values)6.2 to 7.9 p19 to p25 6% (28 of 503 values)7.9 to 10.7 p25 to p31 5% (27 of 503 values)10.7 to 12.9 p31 to p38 6% (30 of 503 values)12.9 to 15.9 p38 to p44 6% (30 of 503 values)15.9 to 20.4 p44 to p50 6% (29 of 503 values)20.4 to 24.7 p50 to p56 6% (29 of 503 values)24.7 to 30 p56 to p62 6% (31 of 503 values)30 to 35.5 p62 to p69 6% (30 of 503 values)35.5 to 41.9 p69 to p75 6% (29 of 503 values)41.9 to 48.6 p75 to p81 6% (29 of 503 values)48.6 to 62.4 p81 to p88 6% (31 of 503 values)62.4 to 80.8 p88 to p94 6% (30 of 503 values)80.8 to 189 p94 to p100 6% (30 of 503 values)0 p0 <1% (1 of 503 values)2 p6 <1% (2 of 503 values)4 p12 <1% (1 of 503 values)6.2 p19 1% (3 of 503 values)7.9 p25 <1% (2 of 503 values)10.7 p31 1% (4 of 503 values)12.9 p38 <1% (1 of 503 values)15.9 p44 <1% (2 of 503 values)20.4 p50 1% (3 of 503 values)24.7 p56 <1% (1 of 503 values)30 p62 <1% (1 of 503 values)35.5 p69 1% (3 of 503 values)41.9 p75 <1% (1 of 503 values)48.6 p81 <1% (2 of 503 values)62.4 p88 <1% (1 of 503 values)80.8 p94 <1% (1 of 503 values)189 p100 <1% (1 of 503 values)
188.9
latency_ms
column tally: 462 distinct, 41 duplicate, 4 missing of 507 entriesdistinct 91% (462 of 507 entries) (424 appearing once)duplicate 8% (41 of 507 entries)missing 1% (4 of 507 entries)
3.39
pavement sparkline of 503 values3.39 to 7.97 p0 to p6 6% (30 of 503 values)7.97 to 10.4 p6 to p12 6% (30 of 503 values)10.4 to 11.8 p12 to p19 6% (30 of 503 values)11.8 to 13.1 p19 to p25 6% (30 of 503 values)13.1 to 15.1 p25 to p31 6% (31 of 503 values)15.1 to 16.9 p31 to p38 6% (30 of 503 values)16.9 to 18.7 p38 to p44 6% (30 of 503 values)18.7 to 20.1 p44 to p50 6% (30 of 503 values)20.1 to 21.9 p50 to p56 6% (29 of 503 values)21.9 to 24.6 p56 to p62 6% (31 of 503 values)24.6 to 28.2 p62 to p69 6% (30 of 503 values)28.2 to 31.8 p69 to p75 6% (31 of 503 values)31.8 to 35.5 p75 to p81 6% (29 of 503 values)35.5 to 42.2 p81 to p88 6% (31 of 503 values)42.2 to 56.1 p88 to p94 6% (30 of 503 values)56.1 to 120 p94 to p100 6% (30 of 503 values)3.39 p0 <1% (1 of 503 values)7.97 p6 <1% (1 of 503 values)10.4 p12 <1% (1 of 503 values)11.8 p19 <1% (2 of 503 values)13.1 p25 <1% (1 of 503 values)15.1 p31 <1% (1 of 503 values)16.9 p38 <1% (2 of 503 values)18.7 p44 <1% (1 of 503 values)20.1 p50 <1% (1 of 503 values)21.9 p56 <1% (2 of 503 values)24.6 p62 <1% (1 of 503 values)28.2 p69 <1% (1 of 503 values)31.8 p75 <1% (2 of 503 values)35.5 p81 <1% (1 of 503 values)42.2 p88 <1% (1 of 503 values)56.1 p94 <1% (1 of 503 values)120 p100 <1% (1 of 503 values)
119.96
referrer
column tally: 363 distinct, 29 duplicate, 115 missing of 507 entriesdistinct 72% (363 of 507 entries) (360 appearing once)duplicate 6% (29 of 507 entries)missing 23% (115 of 507 entries)
""
value proportions of 392 values across 363 distinct values, top 6 shown 7% (28 of 392 values)ref-170003 1% (2 of 392 values)ref-267459 1% (2 of 392 values)ref-942545 <1% (1 of 392 values)ref-280856 <1% (1 of 392 values)ref-521650 <1% (1 of 392 values)other 91% (357 of 392 values) (across 357 distinct values)
ref-783348
legacy_field
column tally: 4 distinct, 8 duplicate, 495 missing of 507 entriesdistinct 1% (4 of 507 entries) (0 appearing once)duplicate 2% (8 of 507 entries)missing 98% (495 of 507 entries)
0
pavement sparkline of 12 values0 to 2 0% (0 of 12 values)2 to 3 0% (0 of 12 values)3 to 4 0% (0 of 12 values)0 p0 to p9 17% (2 of 12 values)2 p18 to p45 33% (4 of 12 values)3 p55 to p73 25% (3 of 12 values)4 p82 to p100 25% (3 of 12 values)
4

A single Series

Pass one sequence and you get a single row. A bare list has no name, so the label shows the value count instead. Numeric values give a spark:

Show code
pavement.summary(daily_signups)   # a bare list — label shows value count
500 entries
column tally: 146 distinct, 354 duplicate, 0 missing of 500 entriesdistinct 29% (146 of 500 entries) (42 appearing once)duplicate 71% (354 of 500 entries)
19
pavement sparkline of 500 values19 to 69 p0 to p6 6% (29 of 500 values)69 to 82 p6 to p12 6% (30 of 500 values)82 to 89 p12 to p19 5% (24 of 500 values)89 to 98.5 p19 to p25 6% (31 of 500 values)98.5 to 105 p25 to p31 6% (29 of 500 values)105 to 109 p31 to p38 5% (23 of 500 values)109 to 115 p38 to p44 6% (28 of 500 values)115 to 122 p44 to p50 6% (29 of 500 values)122 to 128 p50 to p56 6% (28 of 500 values)128 to 134 p56 to p62 4% (22 of 500 values)134 to 139 p62 to p69 6% (28 of 500 values)139 to 144 p69 to p75 5% (26 of 500 values)144 to 151 p75 to p81 6% (28 of 500 values)151 to 160 p81 to p88 6% (28 of 500 values)160 to 172 p88 to p94 6% (30 of 500 values)172 to 228 p94 to p100 6% (30 of 500 values)19 p0 <1% (1 of 500 values)69 p6 <1% (2 of 500 values)82 p12 1% (6 of 500 values)89 p19 <1% (2 of 500 values)98.5 p25 0% (0 of 500 values)105 p31 1% (4 of 500 values)109 p38 1% (7 of 500 values)115 p44 1% (5 of 500 values)122 p50 0% (0 of 500 values)128 p56 1% (5 of 500 values)134 p62 2% (10 of 500 values)139 p69 1% (6 of 500 values)144 p75 0% (0 of 500 values)151 p81 1% (4 of 500 values)160 p88 1% (3 of 500 values)172 p94 <1% (1 of 500 values)228 p100 <1% (1 of 500 values)
228

…and categorical values give a proportion strip:

Show code
pavement.summary(survey)          # a list of strings
125 entries
column tally: 5 distinct, 120 duplicate, 0 missing of 125 entriesdistinct 4% (5 of 125 entries) (0 appearing once)duplicate 96% (120 of 125 entries)
agree
value proportions of 125 values across 5 distinct valuesagree 44% (55 of 125 values)strongly agree 24% (30 of 125 values)neutral 18% (22 of 125 values)disagree 10% (12 of 125 values)strongly disagree 5% (6 of 125 values)
strongly disagree

Drag to reorder

Every summary on this page is drag-to-reorder by default: a small grip handle sits at the left of each column name — grab it and drop the row where you want, and the others slide to make room, handy for sitting two columns next to each other to compare them. Only the grip drags, so the rest of the row keeps its normal cursor and stays text-selectable, and the top summary row stays pinned. It's the page's only JavaScript, scoped per table and purely visual (the new order isn't read back into Python). The grip only appears where that script runs, so notebooks and static exports simply show the plain table — which is why it's harmless to leave on. Pass draggable=False for a guaranteed script-free, static fragment.

Show code
pavement.summary(df)                   # rows drag to reorder by default
pavement.summary(df, draggable=False)  # a script-free, static table

A pandas DataFrame

The call is the same — pavement.summary(df) — for a real DataFrame. Numeric columns become sparks, the species and the boolean flag become proportion strips.

Show code
import pandas as pd
import pavement

df = pd.DataFrame({...})
pavement.summary(df)
4 by 150
column tally: 141 distinct, 9 duplicate, 0 missing of 150 rowsdistinct 94% (141 of 150 rows) (132 appearing once)duplicate 6% (9 of 150 rows)
sepal_length
column tally: 39 distinct, 111 duplicate, 0 missing of 150 entriesdistinct 26% (39 of 150 entries) (7 appearing once)duplicate 74% (111 of 150 entries)
3
pavement sparkline of 150 values3 to 4.7 p0 to p12 10% (15 of 150 values)4.7 to 5.3 p12 to p25 10% (15 of 150 values)5.3 to 5.6 p25 to p38 9% (14 of 150 values)5.6 to 5.8 p38 to p50 5% (8 of 150 values)5.8 to 6 p50 to p62 4% (6 of 150 values)6 to 6.4 p62 to p75 11% (16 of 150 values)6.4 to 6.8 p75 to p88 10% (15 of 150 values)6.8 to 8.1 p88 to p100 11% (17 of 150 values)3 p0 1% (1 of 150 values)4.7 p12 3% (5 of 150 values)5.3 p25 1% (2 of 150 values)5.6 p38 7% (10 of 150 values)5.8 p50 6% (9 of 150 values)6 p62 6% (9 of 150 values)6.4 p75 3% (5 of 150 values)6.8 p88 1% (2 of 150 values)8.1 p100 1% (1 of 150 values)
8.1
sepal_width
column tally: 21 distinct, 129 duplicate, 0 missing of 150 entriesdistinct 14% (21 of 150 entries) (5 appearing once)duplicate 86% (129 of 150 entries)
1.8
pavement sparkline of 150 values1.8 to 2.6 p0 to p12 11% (16 of 150 values)2.6 to 2.7 0% (0 of 150 values)2.7 to 2.9 p25 to p38 7% (11 of 150 values)2.9 to 3 0% (0 of 150 values)3 to 3.1 0% (0 of 150 values)3.1 to 3.2 0% (0 of 150 values)3.2 to 3.4 p75 to p88 7% (11 of 150 values)3.4 to 4.1 p88 to p100 10% (15 of 150 values)1.8 p0 1% (1 of 150 values)2.6 p12 5% (7 of 150 values)2.7 p25 11% (17 of 150 values)2.9 p38 11% (16 of 150 values)3 p50 10% (15 of 150 values)3.1 p62 15% (22 of 150 values)3.2 p75 5% (8 of 150 values)3.4 p88 7% (10 of 150 values)4.1 p100 1% (1 of 150 values)
4.1
species
column tally: 3 distinct, 147 duplicate, 0 missing of 150 entriesdistinct 2% (3 of 150 entries) (0 appearing once)duplicate 98% (147 of 150 entries)
setosa
value proportions of 150 values across 3 distinct valuessetosa 33% (50 of 150 values)versicolor 33% (50 of 150 values)virginica 33% (50 of 150 values)
virginica
measured
column tally: 2 distinct, 148 duplicate, 0 missing of 150 entriesdistinct 1% (2 of 150 entries) (0 appearing once)duplicate 99% (148 of 150 entries)
True
value proportions of 150 values across 2 distinct valuesTrue 93% (139 of 150 values)False 7% (11 of 150 values)
False

Numpy datetime64 and timedelta64 arrays

Raw numpy arrays work too — no pandas or polars needed. datetime64 columns land on a time axis; timedelta64 columns show durations (e.g. 00:01 for one minute).

Show code
import numpy as np
import pavement

data = {
    "event_time": np.array([...], dtype="datetime64[s]"),
    "response_delay": np.array([...], dtype="timedelta64[s]"),
}
pavement.summary(data)
2 by 500
column tally: 500 distinct, 0 duplicate, 0 missing of 500 rowsdistinct 100% (500 of 500 rows) (500 appearing once)
event_time
column tally: 500 distinct, 0 duplicate, 0 missing of 500 entriesdistinct 100% (500 of 500 entries) (500 appearing once)
2024-01-01 00:00
pavement sparkline of 500 values2024-01-01 00:00 to 2024-01-02 07:00 p0 to p6 6% (30 of 500 values)2024-01-02 07:00 to 2024-01-03 14:00 p6 to p12 6% (30 of 500 values)2024-01-03 14:00 to 2024-01-04 21:00 p12 to p19 6% (30 of 500 values)2024-01-04 21:00 to 2024-01-06 04:30 p19 to p25 6% (31 of 500 values)2024-01-06 04:30 to 2024-01-07 12:00 p25 to p31 6% (31 of 500 values)2024-01-07 12:00 to 2024-01-08 19:00 p31 to p38 6% (30 of 500 values)2024-01-08 19:00 to 2024-01-10 02:00 p38 to p44 6% (30 of 500 values)2024-01-10 02:00 to 2024-01-11 09:30 p44 to p50 6% (31 of 500 values)2024-01-11 09:30 to 2024-01-12 17:00 p50 to p56 6% (31 of 500 values)2024-01-12 17:00 to 2024-01-14 00:00 p56 to p62 6% (30 of 500 values)2024-01-14 00:00 to 2024-01-15 07:00 p62 to p69 6% (30 of 500 values)2024-01-15 07:00 to 2024-01-16 14:30 p69 to p75 6% (31 of 500 values)2024-01-16 14:30 to 2024-01-17 22:00 p75 to p81 6% (31 of 500 values)2024-01-17 22:00 to 2024-01-19 05:00 p81 to p88 6% (30 of 500 values)2024-01-19 05:00 to 2024-01-20 12:00 p88 to p94 6% (30 of 500 values)2024-01-20 12:00 to 2024-01-21 19:00 p94 to p100 6% (30 of 500 values)2024-01-01 00:00 p0 <1% (1 of 500 values)2024-01-02 07:00 p6 <1% (1 of 500 values)2024-01-03 14:00 p12 <1% (1 of 500 values)2024-01-04 21:00 p19 <1% (1 of 500 values)2024-01-06 04:30 p25 0% (0 of 500 values)2024-01-07 12:00 p31 <1% (1 of 500 values)2024-01-08 19:00 p38 <1% (1 of 500 values)2024-01-10 02:00 p44 <1% (1 of 500 values)2024-01-11 09:30 p50 0% (0 of 500 values)2024-01-12 17:00 p56 <1% (1 of 500 values)2024-01-14 00:00 p62 <1% (1 of 500 values)2024-01-15 07:00 p69 <1% (1 of 500 values)2024-01-16 14:30 p75 0% (0 of 500 values)2024-01-17 22:00 p81 <1% (1 of 500 values)2024-01-19 05:00 p88 <1% (1 of 500 values)2024-01-20 12:00 p94 <1% (1 of 500 values)2024-01-21 19:00 p100 <1% (1 of 500 values)
2024-01-21 19:00
response_delay
column tally: 155 distinct, 345 duplicate, 0 missing of 500 entriesdistinct 31% (155 of 500 entries) (50 appearing once)duplicate 69% (345 of 500 entries)
00:00:01
pavement sparkline of 500 values00:00:01 to 00:00:04 p0 to p6 3% (15 of 500 values)00:00:04 to 00:00:08 p6 to p12 5% (25 of 500 values)00:00:08 to 00:00:12 p12 to p19 4% (19 of 500 values)00:00:12 to 00:00:18 p19 to p25 5% (23 of 500 values)00:00:18 to 00:00:24 p25 to p31 5% (26 of 500 values)00:00:24 to 00:00:30 p31 to p38 6% (28 of 500 values)00:00:30 to 00:00:37 p38 to p44 4% (22 of 500 values)00:00:37 to 00:00:43 p44 to p50 5% (25 of 500 values)00:00:43 to 00:00:50 p50 to p56 6% (29 of 500 values)00:00:50 to 00:00:58 p56 to p62 5% (25 of 500 values)00:00:58 to 00:01:05 p62 to p69 6% (28 of 500 values)00:01:05 to 00:01:16 p69 to p75 6% (30 of 500 values)00:01:16 to 00:01:40 p75 to p81 6% (29 of 500 values)00:01:40 to 00:02:02 p81 to p88 6% (30 of 500 values)00:02:02 to 00:02:45 p88 to p94 6% (29 of 500 values)00:02:45 to 00:05:28 p94 to p100 6% (30 of 500 values)00:00:01 p0 2% (12 of 500 values)00:00:04 p6 2% (9 of 500 values)00:00:08 p12 1% (6 of 500 values)00:00:12 p19 2% (9 of 500 values)00:00:18 p25 2% (9 of 500 values)00:00:24 p31 1% (6 of 500 values)00:00:30 p38 1% (4 of 500 values)00:00:37 p44 1% (6 of 500 values)00:00:43 p50 1% (7 of 500 values)00:00:50 p56 1% (4 of 500 values)00:00:58 p62 1% (4 of 500 values)00:01:05 p69 1% (3 of 500 values)00:01:16 p75 <1% (2 of 500 values)00:01:40 p81 <1% (2 of 500 values)00:02:02 p88 <1% (2 of 500 values)00:02:45 p94 <1% (1 of 500 values)00:05:28 p100 <1% (1 of 500 values)
00:05:28

A frequency rug

A rug (bins=None) draws one line per distinct value. By default every line spans the full height, so a value that occurs once looks just like one that occurs a hundred times. With proportional_representation=True each line is instead scaled to how often that value occurs: the most common value reaches the full box and the rest reach proportionally less, so the shape of the distribution reads straight off the line lengths — without binning the data away.

The data below is a five-level rating with 97 fours (the most common), 94 threes, 60 fives, 40 twos, and 12 ones. Hover any line for its value, percentile, and count — or the space between two lines for that gap's range (an easier target than a thin line), just like the boxes of a binned pavement.

pavement sparkline of 303 values1 to 2 0% (0 of 303 values)2 to 3 0% (0 of 303 values)3 to 4 0% (0 of 303 values)4 to 5 0% (0 of 303 values)1 p0 to p4 4% (12 of 303 values)2 p4 to p17 13% (40 of 303 values)3 p17 to p48 31% (94 of 303 values)4 p48 to p80 32% (97 of 303 values)5 p80 to p100 20% (60 of 303 values)
Plain rug. Every distinct value is one full-height line — you can see which values occur, but not how often.
pavement sparkline of 303 values1 to 2 0% (0 of 303 values)2 to 3 0% (0 of 303 values)3 to 4 0% (0 of 303 values)4 to 5 0% (0 of 303 values)1 p0 to p4 4% (12 of 303 values)2 p4 to p17 13% (40 of 303 values)3 p17 to p48 31% (94 of 303 values)4 p48 to p80 32% (97 of 303 values)5 p80 to p100 20% (60 of 303 values)
Frequency rug. The same values, each line scaled to its frequency. The line for 4 (the most common) spans the full height; 3 reaches 94/97 of the way, and the rarer values less — the distribution's shape without bins.

A floor (min_representation, default 5% of full) keeps a rare value's line visible rather than letting it collapse to a point; the lines sit on a shared baseline (the bottom, for a horizontal rug) and grow upward, so they read like little bars.

This is what summary reaches for automatically: a numeric column with 16 or fewer distinct values (like rating in the dataframe above) is drawn as a frequency rug rather than smeared into equal-mass bins, so its handful of levels and their counts read straight off the strip.

Expressive box edges

Each bin draws its long top and bottom edges only over itself, and only when one or more values fall strictly inside it. So the box closes around the bins where values are spread out, and opens into a gap wherever the bin's mass sits on a value line instead — letting spread and clumping read straight off the outline. All three below are 8-bin pavements; hover any bin or line for its value range, percentile, and count.

pavement sparkline of 400 values0.2 to 10.8 p0 to p12 12% (49 of 400 values)10.8 to 23.9 p12 to p25 12% (50 of 400 values)23.9 to 34.4 p25 to p38 12% (49 of 400 values)34.4 to 49.1 p38 to p50 12% (49 of 400 values)49.1 to 59.9 p50 to p62 12% (50 of 400 values)59.9 to 75.8 p62 to p75 12% (50 of 400 values)75.8 to 87.4 p75 to p88 12% (50 of 400 values)87.4 to 99.3 p88 to p100 12% (49 of 400 values)0.2 p0 <1% (1 of 400 values)10.8 p12 0% (0 of 400 values)23.9 p25 0% (0 of 400 values)34.4 p38 0% (2 of 400 values)49.1 p50 0% (0 of 400 values)59.9 p62 0% (0 of 400 values)75.8 p75 0% (0 of 400 values)87.4 p88 0% (0 of 400 values)99.3 p100 <1% (1 of 400 values)
Spread throughout. Continuous values fill every bin, so the box stays fully closed end to end.
pavement sparkline of 400 values0.3 to 14.8 p0 to p12 12% (49 of 400 values)14.8 to 26.1 p12 to p25 12% (50 of 400 values)26.1 to 50 p25 to p38 5% (20 of 400 values)50 to 50 0% (0 of 400 values)50 to 50 0% (0 of 400 values)50 to 76.3 p62 to p75 5% (20 of 400 values)76.3 to 87.8 p75 to p88 12% (50 of 400 values)87.8 to 99.6 p88 to p100 12% (49 of 400 values)0.3 p0 <1% (1 of 400 values)14.8 p12 0% (0 of 400 values)26.1 p25 0% (0 of 400 values)50 p38 to p62 40% (160 of 400 values)76.3 p75 0% (0 of 400 values)87.8 p88 0% (0 of 400 values)99.6 p100 <1% (1 of 400 values)
A clump in the middle. A heavy spike of one repeated value gives the central bins no interior: the box opens into a gap there (with a tassel at the repeated value) while the spread-out flanks stay closed.
pavement sparkline of 400 values10 to 10 0% (0 of 400 values)10 to 10 0% (0 of 400 values)10 to 10 0% (0 of 400 values)10 to 25 0% (0 of 400 values)25 to 25 0% (0 of 400 values)25 to 60 0% (0 of 400 values)60 to 90 0% (0 of 400 values)90 to 90 0% (0 of 400 values)10 p0 to p38 46% (182 of 400 values)25 p50 to p62 26% (103 of 400 values)60 p75 14% (57 of 400 values)90 p88 to p100 14% (58 of 400 values)
Only a few values. When every value lands on a bin edge, no bin has an interior at all — the box never closes, leaving just the value lines.

Forcing a complete box

The gapped outline is the default, but show_box=True forces the complete box — the two long edges unbroken across the whole value range — for a rug or a pavement alike, for when a solid outline is wanted regardless of where the values fall. The four below are the same 150 iris sepal_width measurements, drawn each way.

pavement sparkline of 150 values2 to 2.5 p0 to p12 7% (10 of 150 values)2.5 to 2.8 p12 to p25 9% (14 of 150 values)2.8 to 2.9 0% (0 of 150 values)2.9 to 3 0% (0 of 150 values)3 to 3.1 0% (0 of 150 values)3.1 to 3.3 p62 to p75 9% (13 of 150 values)3.3 to 3.6 p75 to p88 12% (18 of 150 values)3.6 to 4.4 p88 to p100 9% (14 of 150 values)2 p0 1% (1 of 150 values)2.5 p12 5% (8 of 150 values)2.8 p25 9% (14 of 150 values)2.9 p38 7% (10 of 150 values)3 p50 17% (26 of 150 values)3.1 p62 7% (11 of 150 values)3.3 p75 4% (6 of 150 values)3.6 p88 3% (4 of 150 values)4.4 p100 1% (1 of 150 values)
Pavement, default. An 8-bin pavement. The values cluster and repeat, so some bins hold no interior point and the box opens into gaps there.
pavement sparkline of 150 values2 to 2.5 p0 to p12 7% (10 of 150 values)2.5 to 2.8 p12 to p25 9% (14 of 150 values)2.8 to 2.9 0% (0 of 150 values)2.9 to 3 0% (0 of 150 values)3 to 3.1 0% (0 of 150 values)3.1 to 3.3 p62 to p75 9% (13 of 150 values)3.3 to 3.6 p75 to p88 12% (18 of 150 values)3.6 to 4.4 p88 to p100 9% (14 of 150 values)2 p0 1% (1 of 150 values)2.5 p12 5% (8 of 150 values)2.8 p25 9% (14 of 150 values)2.9 p38 7% (10 of 150 values)3 p50 17% (26 of 150 values)3.1 p62 7% (11 of 150 values)3.3 p75 4% (6 of 150 values)3.6 p88 3% (4 of 150 values)4.4 p100 1% (1 of 150 values)
Pavement, show_box=True. The same pavement with the box forced complete: the top and bottom edges run unbroken across the full range.
pavement sparkline of 150 values2 to 2.2 0% (0 of 150 values)2.2 to 2.3 0% (0 of 150 values)2.3 to 2.4 0% (0 of 150 values)2.4 to 2.5 0% (0 of 150 values)2.5 to 2.6 0% (0 of 150 values)2.6 to 2.7 0% (0 of 150 values)2.7 to 2.8 0% (0 of 150 values)2.8 to 2.9 0% (0 of 150 values)2.9 to 3 0% (0 of 150 values)3 to 3.1 0% (0 of 150 values)3.1 to 3.2 0% (0 of 150 values)3.2 to 3.3 0% (0 of 150 values)3.3 to 3.4 0% (0 of 150 values)3.4 to 3.5 0% (0 of 150 values)3.5 to 3.6 0% (0 of 150 values)3.6 to 3.7 0% (0 of 150 values)3.7 to 3.8 0% (0 of 150 values)3.8 to 3.9 0% (0 of 150 values)3.9 to 4 0% (0 of 150 values)4 to 4.1 0% (0 of 150 values)4.1 to 4.2 0% (0 of 150 values)4.2 to 4.4 0% (0 of 150 values)2 p0 1% (1 of 150 values)2.2 p1 to p2 2% (3 of 150 values)2.3 p3 to p5 3% (4 of 150 values)2.4 p5 to p7 2% (3 of 150 values)2.5 p7 to p12 5% (8 of 150 values)2.6 p13 to p15 3% (5 of 150 values)2.7 p16 to p21 6% (9 of 150 values)2.8 p22 to p31 9% (14 of 150 values)2.9 p32 to p38 7% (10 of 150 values)3 p38 to p55 17% (26 of 150 values)3.1 p56 to p62 7% (11 of 150 values)3.2 p63 to p71 9% (13 of 150 values)3.3 p72 to p75 4% (6 of 150 values)3.4 p76 to p83 8% (12 of 150 values)3.5 p84 to p87 4% (6 of 150 values)3.6 p88 to p90 3% (4 of 150 values)3.7 p91 to p92 2% (3 of 150 values)3.8 p93 to p96 4% (6 of 150 values)3.9 p97 to p97 1% (2 of 150 values)4 p98 1% (1 of 150 values)4.1 p99 1% (1 of 150 values)4.2 p99 1% (1 of 150 values)4.4 p100 1% (1 of 150 values)
Rug, default. The same data as a rug (bins=None): one line per distinct value and no box edges, the way a rug normally reads — but the spaces between the lines are hover targets too, each reading as that gap's value range (with nothing inside it).
pavement sparkline of 150 values2 to 2.2 0% (0 of 150 values)2.2 to 2.3 0% (0 of 150 values)2.3 to 2.4 0% (0 of 150 values)2.4 to 2.5 0% (0 of 150 values)2.5 to 2.6 0% (0 of 150 values)2.6 to 2.7 0% (0 of 150 values)2.7 to 2.8 0% (0 of 150 values)2.8 to 2.9 0% (0 of 150 values)2.9 to 3 0% (0 of 150 values)3 to 3.1 0% (0 of 150 values)3.1 to 3.2 0% (0 of 150 values)3.2 to 3.3 0% (0 of 150 values)3.3 to 3.4 0% (0 of 150 values)3.4 to 3.5 0% (0 of 150 values)3.5 to 3.6 0% (0 of 150 values)3.6 to 3.7 0% (0 of 150 values)3.7 to 3.8 0% (0 of 150 values)3.8 to 3.9 0% (0 of 150 values)3.9 to 4 0% (0 of 150 values)4 to 4.1 0% (0 of 150 values)4.1 to 4.2 0% (0 of 150 values)4.2 to 4.4 0% (0 of 150 values)2 p0 1% (1 of 150 values)2.2 p1 to p2 2% (3 of 150 values)2.3 p3 to p5 3% (4 of 150 values)2.4 p5 to p7 2% (3 of 150 values)2.5 p7 to p12 5% (8 of 150 values)2.6 p13 to p15 3% (5 of 150 values)2.7 p16 to p21 6% (9 of 150 values)2.8 p22 to p31 9% (14 of 150 values)2.9 p32 to p38 7% (10 of 150 values)3 p38 to p55 17% (26 of 150 values)3.1 p56 to p62 7% (11 of 150 values)3.2 p63 to p71 9% (13 of 150 values)3.3 p72 to p75 4% (6 of 150 values)3.4 p76 to p83 8% (12 of 150 values)3.5 p84 to p87 4% (6 of 150 values)3.6 p88 to p90 3% (4 of 150 values)3.7 p91 to p92 2% (3 of 150 values)3.8 p93 to p96 4% (6 of 150 values)3.9 p97 to p97 1% (2 of 150 values)4 p98 1% (1 of 150 values)4.1 p99 1% (1 of 150 values)4.2 p99 1% (1 of 150 values)4.4 p100 1% (1 of 150 values)
Rug, show_box=True. A rug with the box forced on — the old always-boxed behavior, still available when a framed rug is what you want.

In a notebook

Everything above is just str(pavement.summary(...)) dropped into this page. In Jupyter you skip the str() — the last line of a cell, pavement.summary(df), renders the table inline on its own. And for pandas or polars, import pavement.pandas (or import pavement.polars) adds a .pave accessor: df.pave(), df.pave.spark("age"), df.pave.tally("plan") — or pavement.pandas.enable_repr() to make the summary every DataFrame's default preview. See pandas_polars_demo.html for a full walkthrough.