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 pandas aggregation names 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()