Skip to main content
Back to module
Data Visualization & Storytelling · Charts in Python

Matplotlib essentials

Reading1h 27mLesson 1 of 3 in this module

Build a clearly labelled line chart and bar chart with matplotlib's figure and axes interface.

Why it matters

Matplotlib is the foundation of plotting in Python. pandas' .plot(), seaborn and many other libraries draw with it underneath, so knowing its core model lets you fix any chart, whatever library made it. You will run the plotting code on your own machine (Jupyter, VS Code or Google Colab); the in-browser activity focuses on the data preparation that every chart needs.

The core model: figure and axes

Matplotlib has two layers you will use constantly:

  • Figure: the whole canvas (the image file or window).
  • Axes: one plotting area inside the figure, with its own x-axis, y-axis, title and data. A figure can hold several axes.

Always start with plt.subplots(), which returns both:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(8, 4))   # width, height in inches

Then call methods on ax: ax.plot, ax.bar, ax.set_title, ax.set_xlabel. This "object-oriented" style is clearer than calling plt.plot repeatedly, especially once you have more than one chart in a figure.

A labelled line chart

import pandas as pd
import matplotlib.pyplot as plt

orders = pd.read_csv("orders.csv", parse_dates=["date"])
monthly = orders.groupby(orders["date"].dt.strftime("%Y-%m"))["revenue"].sum()

fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(monthly.index, monthly.values, marker="o", color="#1b9e77", linewidth=2)
ax.set_title("Monthly revenue, Jan to May 2026", loc="left")
ax.set_xlabel("Month")
ax.set_ylabel("Revenue ($)")
ax.set_ylim(bottom=0)                     # honest baseline
ax.spines[["top", "right"]].set_visible(False)
ax.grid(axis="y", color="#dddddd", linewidth=0.8)
fig.tight_layout()
fig.savefig("monthly_revenue.png", dpi=150)

What each part does:

  • groupby(...).sum() turns many orders into one value per month. Getting this step right is most of the work, which is why the activity practises it.
  • marker="o" shows where the actual data points are, useful with few periods.
  • set_ylim(bottom=0) is optional for line charts, but it avoids exaggerating small changes when your audience might over-read the slope.
  • tight_layout() stops labels being cut off; savefig writes a file at a sensible resolution.

A sorted bar chart

by_region = orders.groupby("region")["revenue"].sum().sort_values()

fig, ax = plt.subplots(figsize=(6, 3))
bars = ax.barh(by_region.index, by_region.values, color="#7570b3")
ax.bar_label(bars, fmt="{:,.0f}", padding=3)
ax.set_title("Revenue by region", loc="left")
ax.set_xlabel("Revenue ($)")
ax.spines[["top", "right"]].set_visible(False)
fig.tight_layout()

barh draws horizontal bars, which suit text labels. Matplotlib draws the first bar at the bottom, so sorting ascending puts the largest at the top. bar_label (matplotlib 3.4+) adds value labels, and fmt="{:,.0f}" adds thousands separators.

Several charts in one figure

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4))
ax1.plot(monthly.index, monthly.values)
ax2.barh(by_region.index, by_region.values)
fig.suptitle("Q1 to Q2 sales overview")

plt.subplots(rows, cols) returns an array of axes. You will use this for small multiples later in the module.

Saving and sharing

  • Use savefig("name.png", dpi=150) for slides and documents, or .svg for crisp scaling on the web.
  • Set figsize before plotting; resizing an image afterwards blurs text.
  • In Jupyter, a chart shows automatically at the end of a cell; in scripts, call plt.show().

Common mistakes

  • Mixing the plt. and ax. styles in the same figure. Titles end up on the wrong chart. Pick ax. methods.
  • Plotting unaggregated data. Plotting 10,000 raw orders as a line gives a scribble. Aggregate first.
  • Unsorted time. If months are strings, make sure they are sorted ("2026-10" sorts correctly; "Oct 2026" does not). Using ISO "YYYY-MM" strings or real dates avoids this.
  • Missing units. "Revenue" alone does not say dollars or thousands of dollars.
  • Default titles. Matplotlib adds none by default; always add one, ideally stating the takeaway.

Quick recap

  • fig, ax = plt.subplots() then call methods on ax.
  • Aggregate with pandas, then plot: ax.plot for time, ax.barh for sorted categories.
  • Label axes with units, set honest baselines, remove extra spines, tight_layout(), savefig.

Try it

In the Do tab, use pandas to compute the monthly series and the sorted region totals that feed these two charts, plus a takeaway title.

Also in this lesson: