Your first charts

Matplotlib is the drawing engine behind most Python charts, including the ones pandas and seaborn produce for you. Learn one small recipe and you can plot almost anything.

The recipe every chart follows

  1. Create a Figure (the canvas) and one or more Axes (the plot panels) with plt.subplots().
  2. Draw your data on an Axes: ax.plot(), ax.bar(), ax.scatter().
  3. Label it, tidy it, then show or save it.
import matplotlib.pyplot as plt

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
sales = [120, 150, 170, 160, 195, 210]        # ₹ '000, electronics store in Nashik

fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(months, sales, marker="o", color="#F5A524", linewidth=2)
ax.set_title("Monthly sales (₹ '000)")
ax.set_xlabel("Month")
ax.set_ylabel("Sales")
ax.grid(alpha=.3)
fig.tight_layout()
plt.show()

figsize is in inches, so (8, 4) gives a wide chart that fits a slide. fig.tight_layout() stops long labels from being clipped.

Bar charts compare categories

Swap ax.plot for ax.bar, and sort the categories so the reader does not have to.

pairs = sorted(zip([48.2, 31.5, 18.9, 12.4],
                   ["Mumbai", "Pune", "Nagpur", "Nashik"]))
revenue, cities = zip(*pairs)                  # ascending, so barh reads top-down

fig, ax = plt.subplots(figsize=(7, 4))
bars = ax.barh(cities, revenue, color="#2B7A78")
ax.bar_label(bars, fmt="%.1f", padding=3)
ax.set_xlabel("Revenue (₹ lakh)")
ax.set_title("Revenue by city, FY 2025-26")

Horizontal bars (barh) are kinder to long city names than rotated tick labels, and ax.bar_label prints the value at the end of each bar so no one has to squint at the axis.

Scatter shows a relationship

import numpy as np

rng = np.random.default_rng(7)
ad_spend = rng.uniform(10, 90, 40)                         # ₹ '000
units = 60 + 2.1 * ad_spend + rng.normal(0, 25, 40)

fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(ad_spend, units, s=45, alpha=.7, edgecolor="white")
ax.set_xlabel("Ad spend (₹ '000)")
ax.set_ylabel("Units sold")
ax.set_title("Does ad spend move units?")

alpha makes overlapping points visible, and s controls marker size.

Which method for which job

Method Draws Question it answers
ax.plot Line How did sales move over the quarter?
ax.bar / ax.barh Bars Which city sells the most?
ax.scatter Points Does ad spend drive units?
ax.hist Histogram How are bill values spread?
ax.fill_between Shaded band What is the best-to-worst range?

Common mistakes

  • Calling plt.show() before fig.savefig(). In a script the figure is cleared, so the saved file is blank. Save first.
  • Leaving axes unlabelled. "Sales" means nothing without rupees, units and a period.
  • Using ax.plot() for categories such as cities; a line implies an order that does not exist.
  • Drawing dozens of series on one Axes. Three or four lines is usually the limit before the chart turns into spaghetti.
  • Forgetting that plt.subplots() returns a tuple: fig, ax = plt.subplots(), not ax = plt.subplots().

Practice

Build a small DataFrame of six months of sales for three stores. Draw a line chart of the chain total, a sorted horizontal bar chart of store totals with bar_label, and a scatter of footfall against sales. Give each chart a title, axis labels with units, and save all three as PNG files.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India