Learning Goals
3 min- Install matplotlib;
import matplotlib.pyplot as plt. - Draw a bar chart with
plt.bar(x, y). - Title, axis labels, rotated x-ticks.
- Annotate bars with their values.
- Save the figure to PNG.
Warm-Up · 4 Lines, 1 Chart
5 minpip install matplotlib
import matplotlib.pyplot as plt products = ["Roti", "Milo", "Nasi", "Teh"] revenue = [120, 95, 180, 60] plt.bar(products, revenue) plt.show()
You'll get a window with four blue bars. It works. Now we make it presentable.
Default matplotlib is ugly on purpose — it's the canvas you customise. Five extra lines (title, labels, color, rotation, value text) turn the warm-up plot into something you'd ship.
New Concept · plt.bar & the Customisations
14 minPyplot vs OO
Two styles exist; both work. We'll use OO (object-oriented) — it scales to subplots:
import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(8, 5)) ax.bar(products, revenue) plt.show()
Title + axis labels
ax.set_title("Revenue by product · May 2026") ax.set_xlabel("Product") ax.set_ylabel("Revenue (RM)")
Colour and edge
bars = ax.bar(products, revenue, color="#4a90e2", edgecolor="black", linewidth=0.5)
Rotated x labels (when names are long)
ax.tick_params(axis="x", rotation=30) # or plt.xticks(rotation=30, ha="right")
Value annotations on each bar
for bar in bars: h = bar.get_height() ax.text(bar.get_x() + bar.get_width() / 2, h + 2, f"{h}", ha="center", va="bottom", fontsize=9)
Tight layout + save
fig.tight_layout() fig.savefig("revenue.png", dpi=200)
Worked Example · Polished Bar Chart
12 min# bar.py — production-quality bar chart import matplotlib.pyplot as plt products = ["Roti", "Milo", "Nasi", "Teh"] revenue = [120, 95, 180, 60] fig, ax = plt.subplots(figsize=(8, 5)) bars = ax.bar(products, revenue, color=["#4a90e2", "#e2884a", "#4ae28d", "#e24a8d"], edgecolor="black", linewidth=0.5) ax.set_title("Revenue by product · May 2026", fontsize=14, pad=10) ax.set_xlabel("Product") ax.set_ylabel("Revenue (RM)") ax.set_ylim(0, max(revenue) * 1.15) ax.grid(axis="y", linestyle="--", alpha=0.4) for bar in bars: h = bar.get_height() ax.text(bar.get_x() + bar.get_width() / 2, h + 3, f"RM {h}", ha="center", va="bottom", fontsize=10) fig.tight_layout() fig.savefig("revenue.png", dpi=200) plt.show()
Open revenue.png in any image viewer. You get a chart you could paste straight into a school presentation. Five elements made the difference:
- Distinct colours per bar.
- Annotated values above each bar.
- Horizontal grid for easier reading.
- Extra y-axis headroom so labels don't collide.
tight_layoutprevents the title or labels being clipped.
Try It Yourself
13 minUse ax.barh(...) for horizontal bars instead. Useful when names are long.
Sort the products so the tallest bar is on the left. Then add a colour scheme that goes dark → light.
Hint
import matplotlib.cm as cm pairs = sorted(zip(products, revenue), key=lambda p: -p[1]) products, revenue = zip(*pairs) colors = cm.Blues([1 - i / len(products) for i in range(len(products))]) ax.bar(products, revenue, color=colors)
Compare last month vs this month: two bars per product, side by side.
Hint
import numpy as np last = [110, 90, 160, 55] this = [120, 95, 180, 60] x = np.arange(len(products)) w = 0.4 fig, ax = plt.subplots() ax.bar(x - w/2, last, w, label="Apr") ax.bar(x + w/2, this, w, label="May") ax.set_xticks(x, products) ax.legend()
Mini-Challenge · Bar From a CSV
8 minRead clean.csv, compute revenue per product with pandas, draw a sorted bar chart with annotations, save to revenue.png.
Show one possible solution
import pandas as pd, matplotlib.pyplot as plt df = pd.read_csv("clean.csv") df["total"] = df["quantity"] * df["price"] rev = (df.groupby("product")["total"].sum() .sort_values(ascending=False)) fig, ax = plt.subplots(figsize=(8, 5)) bars = ax.bar(rev.index, rev.values, color="#4a90e2", edgecolor="black") ax.set_title("Revenue by product") ax.set_ylabel("RM") for b in bars: ax.text(b.get_x() + b.get_width()/2, b.get_height() + 0.3, f"RM {b.get_height():.0f}", ha="center") fig.tight_layout() fig.savefig("revenue.png", dpi=200)
Recap
3 minBars in 4 lines; presentable bars in 10. Use the OO style (fig, ax = plt.subplots()) — it carries over to subplots tomorrow. Always title + label + save. Annotations beat tooltips for static reports.
Homework
4 minDraw a polished bar chart of any aggregate from your real CSV. Hit all five rules: title, labels, sorted, annotated, saved as PNG.