Broken Timeline Plot Gallery¶
Broken timeline plots show when a category had meaningful activity, drawing a horizontal bar for every continuous run of data and leaving the gaps blank. They turn questions about coverage, seasonality, and operational continuity into a single glance.
Broken timeline plots excel at:
- Data quality reads: spot reporting gaps and ingestion outages across stores or systems
- Operational continuity: surface store closures, refits, and other run-time interruptions
- Seasonal availability: visualise when each SKU or category was actually in stock and selling
- Threshold-driven activity: combine
threshold_valuewithagg_functo see when a metric cleared a meaningful bar
import matplotlib.pyplot as plt
import pandas as pd
from openretailscience.plots import broken_timeline
Basic Broken Timeline¶
The simplest call: pass a category column and a value column, and the function draws one bar per category for every continuous run of dates with data. Reach for this when a coverage question hits the desk: did all my stores report?, which days are missing from the feed?
ax = broken_timeline.plot(
store_sales,
category_col="store_id",
value_col="sales_amount",
eyebrow="Operational continuity",
title="Camden was the only London store to report every day in January",
subtitle="Daily sales activity by London store, January 2024",
)
plt.show()
Weekly Period Aggregation¶
Set period="W" to bucket data into ISO weeks before drawing. Use weekly buckets when the natural unit of analysis is the week rather than the day, or when daily data is patchy enough that day-level gaps are noisy rather than informative. The bar widths and gap thresholds adjust to match the chosen period.
ax = broken_timeline.plot(
category_sales,
category_col="product_category",
value_col="weekly_sales",
period="W",
eyebrow="Seasonal rotation",
title="Winter Boots taper as Spring Jackets ramp up; Basics had a two-week supply gap",
subtitle="Weekly sales activity by product category, Q1 2024",
)
plt.show()
Threshold Filtering¶
threshold_value drops any period whose value falls below the cutoff before the bars are drawn. Use it to focus on meaningful activity rather than the long tail of trickle days. The remaining bars show every period that cleared the bar, gap segments show every period that didn't.
ax = broken_timeline.plot(
channel_revenue,
category_col="sales_channel",
value_col="daily_revenue",
threshold_value=1_000,
eyebrow="Channel activity",
title="Storefront and Online clear $1K every day; Catalog and Phone Orders only sometimes",
subtitle="Days exceeding $1,000 daily revenue by channel, Feb 1 to Feb 21 2024",
)
plt.show()
Aggregation Function with Threshold¶
Pair agg_func with a period longer than a day to control what the per-period value means. Use "mean" to read average daily activity per week (or month) rather than the total. Combined with threshold_value, this surfaces the periods that sustained a target average rather than the periods that hit the target on any single day.
ax = broken_timeline.plot(
regional_visitors,
category_col="region",
value_col="daily_visitors",
period="W",
agg_func="mean",
threshold_value=400,
eyebrow="Regional traffic",
title="North sustained 400+ avg daily visitors every week; South and West each had multi-week dry spells",
subtitle="Weeks where mean daily visitors exceeded 400, by region, Q1 2024",
source_text="Source: Store Footfall Counters",
)
plt.show()