Learning Goals
3 min- Draw a basic line chart with
ax.plot(x, y). - Plot multiple series on the same axes with a legend.
- Format date axes with
matplotlib.dateslocators. - Overlay a 7-day rolling average to smooth a noisy series.
Warm-Up · A 1-Line Plot
5 minimport matplotlib.pyplot as plt days = list(range(1, 11)) sales = [3, 5, 4, 6, 8, 7, 9, 11, 10, 12] plt.plot(days, sales) plt.show()
Lines are for ordered data — usually time. The x-axis tells your story; pick a sensible range, format dates legibly, and only show as many ticks as the eye can read.
New Concept · Lines, Dates, Smoothing
14 minLine style + markers
ax.plot(x, y, color="#4a90e2", linewidth=2, marker="o", label="actual")
Multiple series
ax.plot(x, y1, label="Apr") ax.plot(x, y2, label="May") ax.legend()
Date axis
import matplotlib.dates as mdates import pandas as pd df = pd.read_csv("daily.csv", parse_dates=["date"]) fig, ax = plt.subplots(figsize=(10, 5)) ax.plot(df["date"], df["sales"]) # major tick every month, format as "May 2026" ax.xaxis.set_major_locator(mdates.MonthLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %Y")) fig.autofmt_xdate()
autofmt_xdate rotates labels so they don't overlap.
Rolling average
df["rolling7"] = df["sales"].rolling(7).mean() ax.plot(df["date"], df["sales"], alpha=0.4, label="daily") ax.plot(df["date"], df["rolling7"], linewidth=2, label="7-day avg")
The translucent daily line + the bold rolling line shows both signal and noise — a great default for any noisy daily metric.
Annotate a key moment
peak = df.loc[df["sales"].idxmax()] ax.annotate(f"peak: {int(peak['sales'])}", xy=(peak["date"], peak["sales"]), xytext=(peak["date"], peak["sales"] + 30), arrowprops={"arrowstyle": "->"})
Worked Example · Daily Revenue with Trend Line
12 min# daily_revenue.py import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates df = pd.read_csv("clean.csv", parse_dates=["date"]) df["total"] = df["quantity"] * df["price"] daily = (df.groupby(df["date"].dt.date)["total"].sum() .rename("daily").to_frame()) daily.index = pd.to_datetime(daily.index) daily["roll7"] = daily["daily"].rolling(7).mean() fig, ax = plt.subplots(figsize=(10, 5)) ax.plot(daily.index, daily["daily"], color="#4a90e2", alpha=0.35, label="daily") ax.plot(daily.index, daily["roll7"], color="#1f5fa8", linewidth=2.5, label="7-day avg") ax.set_title("Daily revenue · 7-day rolling") ax.set_ylabel("RM") ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO)) ax.xaxis.set_major_formatter(mdates.DateFormatter("%d %b")) ax.grid(axis="y", linestyle="--", alpha=0.4) ax.legend() fig.autofmt_xdate() fig.tight_layout() fig.savefig("revenue_trend.png", dpi=200) plt.show()
Read the diff
One faded line shows the actual daily revenue (noisy); a bold line shows the trend. The Monday-locator and dd-Mon formatter keep the date axis readable. PNG saved at 200 DPI — looks crisp on a slide.
Try It Yourself
13 minPlot any column from a time-series CSV against its date column. Add a title and y-label.
Plot two metrics on the same axes with a legend (e.g., open vs done counts, daily vs weekly revenue).
When two series have very different scales, use ax2 = ax.twinx() to give them their own y-axes.
Hint
fig, ax = plt.subplots() ax.plot(dates, revenue, color="b", label="revenue") ax.set_ylabel("Revenue (RM)", color="b") ax2 = ax.twinx() ax2.plot(dates, orders, color="r", label="orders") ax2.set_ylabel("Orders", color="r")
Mini-Challenge · Compare Years
8 minFrom a daily dataset spanning ≥ 2 years, plot one line per year, x-axis = day-of-year (1-365). The result lets you eyeball seasonal differences.
Show one possible solution
df["doy"] = df["date"].dt.dayofyear df["year"] = df["date"].dt.year fig, ax = plt.subplots(figsize=(10, 5)) for yr, g in df.groupby("year"): ax.plot(g["doy"], g["sales"].rolling(7).mean(), label=str(yr)) ax.legend() ax.set_title("Daily sales — 7-day avg by year") ax.set_xlabel("Day of year")
Rolling averages let multi-year overlays be readable. Without smoothing, four lines on top of each other become noise.
Recap
3 minax.plot for lines. Multiple series + legend for comparison. Date axes via matplotlib.dates. A 7-day rolling average tames noisy daily data. Save as PNG. Tomorrow: pie + scatter for proportions and correlations.
Homework
4 minDraw a time-series chart from your real CSV that includes a 7-day rolling average overlay, a date axis formatted readably, and an annotation marking the peak point. Save the PNG.