Discord

3Data Manipulation 3.1Data Manipulation Libraries

3.1.2 Matplotlib

Draw the four charts you will use most (a loss curve, a scatter plot, a histogram and a bar chart) and make them readable.

Why draw your data?

A table of numbers can hide patterns that a picture makes obvious. One chart may show you that two groups are clearly separated, one value is wildly wrong or a model stopped improving several epochs ago. In an IOAI task, we usually draw charts for ourselves: to understand the data before choosing a model and to see how training is going.

Matplotlib is the standard Python library for charts, and it is available in the contest. You do not need to learn the whole library. We will focus on four charts you will use again and again, plus the few labels and settings that make them readable.

We will use pandas and the Iris dataset from Pandas, so complete that module first if these are not familiar yet.

How to learn it

You do not need to use every resource below. Choose the format that helps you learn, then draw the examples yourself.

The basic recipe

Almost every chart follows the same small recipe. We will reuse it throughout this module:

INPUTPython
import matplotlib.pyplot as plt

fig, ax = plt.subplots()      # 1. make an empty figure with one chart area
ax.plot([1, 2, 3], [4, 1, 5]) # 2. draw something on it
ax.set_xlabel("x")            # 3. label the axes
ax.set_ylabel("y")
plt.show()                    # 4. show it
  • fig is the whole figure—the complete picture. ax is one chart inside it, with its own axes. We draw on ax.
  • In a notebook, the chart appears directly below the cell. plt.show() also makes sure you see only the chart, without an extra line of text above it.
  • The fifth step is the one we are most likely to skip: look at the chart and ask what it tells you. Drawing it is not the goal; learning something from it is.

You will also see code that calls plt.plot(...) directly without creating fig, ax. That is fine for a quick one-off chart. We will use the fig, ax style because the same pattern keeps working when we later place two charts side by side. You only need to become comfortable with this one style for now.

Common charts

Line chart

A line chart shows how something changes from one step to the next. In machine learning, you will often use one for a loss curve: how wrong the model is after each round of training, called an epoch, on both training data and held-out validation data. The numbers below are made up so we can practise reading a common pattern.

INPUTPython
import matplotlib.pyplot as plt

epochs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
train_loss = [1.00, 0.72, 0.55, 0.45, 0.38, 0.33, 0.29, 0.26, 0.24, 0.22]
val_loss = [1.05, 0.80, 0.64, 0.56, 0.52, 0.50, 0.50, 0.51, 0.53, 0.56]

fig, ax = plt.subplots()
ax.plot(epochs, train_loss, label="training")
ax.plot(epochs, val_loss, label="validation")
ax.set_xlabel("Epoch")
ax.set_ylabel("Loss")
ax.set_title("Loss during training")
ax.legend()
plt.show()
Line chart titled Loss during training, with epochs 1 to 10 on the x-axis and loss on the y-axis. The blue training line falls steadily from 1.0 to about 0.22. The orange validation line falls from about 1.05 to 0.5 by epoch 6, stays flat, then rises to about 0.56 by epoch 10.
Training loss keeps falling, but validation loss stops improving around epoch 6 and then rises.

label= gives each line a name, and ax.legend() displays those names in a box. Now let us read the chart. The model keeps improving on its training data, but after about epoch 6 it gets worse on new data. It has started to memorise the training set. This is called overfitting, and Underfitting and Overfitting explains it properly. For now, notice that the chart helps us decide when to stop training.

Scatter plot

A scatter plot draws one dot for each row. One column decides the horizontal position and another decides the vertical position. If we colour the dots by class, we can see whether those classes are easy to separate:

INPUTPython
from sklearn.datasets import load_iris

iris = load_iris(as_frame=True).frame
species = ["setosa", "versicolor", "virginica"]

fig, ax = plt.subplots()
for number, name in enumerate(species):
    flowers = iris[iris["target"] == number]
    ax.scatter(flowers["petal length (cm)"],
               flowers["petal width (cm)"], label=name)
ax.set_xlabel("Petal length (cm)")
ax.set_ylabel("Petal width (cm)")
ax.legend()
plt.show()
Scatter plot of petal width against petal length for 150 iris flowers. Blue setosa dots form a tight group at the bottom left, around length 1.5 and width 0.25. Orange versicolor dots sit in the middle, and green virginica dots at the top right, with a small overlap between those two.
Setosa is far away from the other two species; versicolor and virginica overlap a little.

The loop draws each species separately, giving each one its own colour and legend entry. enumerate gives us the number (0, 1, 2) and name together. We can already make a useful prediction from the chart: a sensible model should separate setosa easily, while most mistakes will happen where versicolor and virginica overlap. K-Nearest Neighbors will work directly with patterns like this one.

Histogram

A histogram splits the range of one column into intervals called bins, then counts how many rows fall into each one:

INPUTPython
fig, ax = plt.subplots()
ax.hist(iris["petal length (cm)"], bins=20)
ax.set_xlabel("Petal length (cm)")
ax.set_ylabel("Number of flowers")
plt.show()
Histogram of petal length for 150 iris flowers in 20 bins. A tall narrow group of bars sits between 1 and 2 cm, then there is an empty gap, then a wider group of bars between 3 and 7 cm.
Two clear groups: short petals (setosa) and longer ones (the other two species).

bins controls how many bars we use. You do not need to find a perfect number immediately; try a reasonable value and look at the result. Histograms are a quick way to spot strange values, such as a negative length or an age of 200, before they confuse a model. Data Cleaning shows what to do with them.

Bar chart

A bar chart compares one number across categories. Here, we will compare how many students come from each city:

INPUTPython
cities = ["Delhi", "Mumbai", "Pune"]
students = [3, 2, 1]

fig, ax = plt.subplots()
ax.bar(cities, students)
ax.set_ylabel("Students")
plt.show()
Bar chart with three bars: Delhi 3 students, Mumbai 2, Pune 1.
The counts from value_counts in the Pandas module, drawn as bars.

In a classification task, draw a bar chart of the label counts. You will see at a glance whether one class is much rarer than the others, which affects how we should measure the model.

Two charts side by side

plt.subplots(1, 2) gives us one row containing two chart areas. figsize sets the figure size in inches as (width, height). We draw on the left chart with axes[0] and the right chart with axes[1]:

INPUTPython
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
axes[0].hist(iris["sepal length (cm)"], bins=20)
axes[0].set_xlabel("Sepal length (cm)")
axes[1].hist(iris["petal length (cm)"], bins=20)
axes[1].set_xlabel("Petal length (cm)")
plt.show()
Two histograms side by side. The left one, sepal length, is a single spread-out hump from about 4.3 to 7.9 cm. The right one, petal length, shows the two separate groups seen before.
Side by side, it is easy to see that petal length separates the flowers far better than sepal length.

Placing charts next to each other makes comparisons much easier. Here we can immediately see that petal length is the more useful measurement.

A shortcut from pandas

pandas can call Matplotlib for us. iris["petal length (cm)"].plot.hist(bins=20) draws the same histogram as above, while df["city"].value_counts().plot.bar() draws a bar chart straight from the data. This shortcut is useful for a first look. Move to fig, ax when you need more control over the details.

Make it readable

A chart only helps if you can read it. Before moving on, check these few things:

  • Axis labels, with units: "Petal length (cm)", not "x". ax.set_xlabel, ax.set_ylabel.
  • A legend when there is more than one line or colour: label= on each, then ax.legend().
  • A title if the chart will be looked at later: ax.set_title.
  • A sensible size: plt.subplots(figsize=(8, 4)) for wide time series.
  • Saving: fig.savefig("loss.png", dpi=150, bbox_inches="tight") writes the chart to a file.

You can also choose colours, markers and line styles, for example ax.plot(x, y, color="red", marker="o", linestyle="--"). Do not spend too long decorating exploratory charts; clarity is enough. The plot types page shows the other options when you need them.

Common mistakes

These mistakes are all easy to make. When a chart looks wrong, check the simple causes below before rewriting the plotting code.

Mistake What you see Fix
The two lists have different lengths ValueError: x and y must have same first dimension, but have shapes (10,) and (9,) Check len(x) and len(y); a value is missing from one list.
No label=, but ax.legend() An empty legend, or the warning "No artists with labels found to put in legend" Add label="..." to each plot or scatter.
No axis labels No error, just a chart nobody understands a week later Always label the axes.
Several charts come out on top of each other Lines from different charts end up in one picture Start each new chart with fig, ax = plt.subplots().

Check yourself

Try each exercise before opening its answer. If you are unsure which chart to choose, first ask what relationship or comparison you want the picture to show.

More practice

CodeChef's Matplotlib course has small problems after each lesson; it is in the practice table below. Then open any dataset you have, such as one from a past IOAI task, and draw one of each of the four charts. For every chart, ask yourself: what can I see here that the table did not show me?

What comes next

If you can draw these four charts, label them and explain what each one shows, you know enough Matplotlib to continue. We can look up extra chart types and styling options when a later task needs them.

  • Data Cleaning: charts and describe() will show you problems in the data; this module shows how to fix them.

Resources

SourceTitleWhy read it
MatplotlibQuick start guideThe official introduction: figures, axes and the basic plotting calls.
MatplotlibPlot typesA picture of every basic chart with its code. Handy when you know what you want but not what it is called.
Jake VanderPlasPython Data Science Handbook, chapter 4A free book chapter on Matplotlib, with line plots, scatter plots and histograms.
Corey SchaferMatplotlib Tutorial (Part 1)The first video of a well-known series.
Kaggle LearnData VisualizationShort lessons with exercises using seaborn, a library built on Matplotlib.
seabornUser guide and tutorialFor when you want nicer statistical charts in fewer lines.

Practice problems

SolvedSourceProblemDifficultyTags
CodeChef Learn Matplotlib: practice problems Easy plots

Finished this module? Mark it done.

Comments

Stuck on something, spotted a mistake, or found a resource that helped you? Tell us below.

Loading comments