Time Plot Gallery¶
Time plots aggregate transactional data into period buckets (daily, weekly, monthly) and trace the result as a line, making them the workhorse for any retail trend question. They show the shape of activity over time so the eye can land on direction, level shifts, and seasonality at a glance.
Time plots excel at:
- Trend tracking: see whether daily revenue is climbing, plateauing, or rolling over
- Seasonality: surface holiday spikes, summer dips, weekday/weekend rhythms
- Promo impact: anchor a level shift to the date a campaign or price change went live
- Category comparisons: overlay a few categories or stores on the same axis to read relative performance
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from openretailscience.plots import time
from openretailscience.plots.styles.graph_utils import set_axis_shorthand
Basic Time Series¶
The simplest call: pass the value column and the function aggregates it by day. Reach for this when the question is what does the recent rhythm look like: weekend lifts, weekday baselines, and one-off spikes all read at a glance.
ax = time.plot(
fortnight_revenue,
value_col="revenue",
eyebrow="Daily revenue",
title="Valentine's Day cleared every other day in the two-week window",
subtitle="Daily revenue ($), Feb 1 to Feb 14 2024",
y_label="Revenue ($)",
)
set_axis_shorthand(ax.yaxis)
plt.show()
Different Time Periods¶
Use period to roll the daily data up into wider buckets: "D" (default), "W", or "M". Pick the period that matches the time horizon of the question: daily for a two-week diagnostic, monthly for an annual review. Aggregating up smooths out weekday noise so seasonality reads cleanly.
ax = time.plot(
annual_sales,
value_col="sales",
period="M",
eyebrow="Holiday seasonality",
title="December delivered $806K, more than double the monthly average",
subtitle="Total monthly sales ($), 2023",
y_label="Sales ($)",
)
set_axis_shorthand(ax.yaxis)
plt.show()
Different Aggregation Functions¶
agg_func controls what the bucket value means: "sum" (default) totals up the period, "mean" gives the per-row average. Use "mean" when the row count varies between periods and you care about the typical value (e.g. average order value) rather than total volume. Other aggregations matplotlib/pandas accepts work too: "max", "min", "count", "nunique".
ax = time.plot(
transactions,
value_col="order_value",
period="W",
agg_func="mean",
eyebrow="Average order value",
title="Loyalty promo on June 3 lifted weekly AOV from \\$65 to \\$83",
subtitle="Mean order value per week, Apr 22 to Jul 14 2024",
y_label="AOV ($)",
)
set_axis_shorthand(ax.yaxis)
plt.show()
Grouped by Category¶
Pass group_col to draw one line per category from a long-format DataFrame. Each group gets a distinct hue from the categorical palette so the lines stay distinguishable. Best with three to six groups; beyond that the colors start to blur and end-of-line labels (next example) read better than a legend.
ax = time.plot(
category_sales,
value_col="revenue",
group_col="category",
period="W",
eyebrow="Category performance",
title="Apparel weekly revenue more than doubles while Home falls by nearly half",
subtitle="Weekly revenue ($) by category, 12-week window",
y_label="Revenue ($)",
legend_title="Category",
move_legend_outside=True,
)
set_axis_shorthand(ax.yaxis)
plt.show()
End-of-Line Legend¶
Pass legend_style="end_of_line" to drop the boxed legend and place a colored series label at the right end of each line instead. The label sits next to the data it describes, so the eye doesn't have to bounce between a swatch and the line. Reads cleaner with three to five series; more than that and the labels start crowding each other (the function bumps overlapping labels apart vertically and draws a leader back to the line end).
ax = time.plot(
category_sales,
value_col="revenue",
group_col="category",
period="W",
legend_style="end_of_line",
eyebrow="Category performance",
title="End-of-line labels sit beside each line instead of in a separate box",
subtitle="Weekly revenue ($) by category, 12-week window",
y_label="Revenue ($)",
)
set_axis_shorthand(ax.yaxis)
plt.show()
Source Attribution¶
source_text adds a small attribution line below the plot, useful for export-ready images that will live outside the notebook. Pair it with eyebrow, subtitle, and a clear y_label for a chart that reads as a finished artifact.
ax = time.plot(
annual_sales,
value_col="sales",
period="M",
eyebrow="Holiday seasonality",
title="November and December together account for nearly a third of annual sales",
subtitle="Total monthly sales ($), 2023",
y_label="Sales ($)",
source_text="Source: Internal Sales Database",
)
set_axis_shorthand(ax.yaxis)
plt.show()