#data science#data visualization#matplotlib#pyplot#python#numpy

Matplotlib Crash Course

A hands-on crash course covering matplotlib's pyplot API and object-oriented interface: line plots, scatter, bar, histograms, box plots, subplots, and axis controls.

May 20, 2026 at 10:30 AM8 min readFollowFollow (Hindi)

Topics You Will Master

Core plotting concepts of Matplotlib's pyplot API
Building common plot types: line, scatter, bar, histograms, and box plots
Formatting subplots and managing multiple axes layouts
Customizing tickers, labels, and scientific scalar notations
Best For

Developers and data scientists looking to master custom figure creation and plot styling.

Expected Outcome

Mastery over Matplotlib's layout system for building customized 2D plots.

Matplotlib is the foundational plotting engine of the Python data science stack. Nearly every high-level library, including Pandas and Seaborn, is a wrapper around Matplotlib.

Matplotlib provides complete, low-level control over figures, axes, styles, and ticks for static and interactive 2D plotting. By mastering its layout system, you gain the ability to build custom compound plots and adjust every visual element on the canvas.

In this tutorial, you will learn how to build visualizations using both the functional pyplot interface and the object-oriented API. You will construct line, scatter, bar, histogram, and box plots, and configure subplots and ticks.

Prerequisites: Python 3.x, Matplotlib, NumPy.

Setup

Before plotting, you must set up the environment by importing the required visualization and numerical computing libraries.

Imports and Configuration

Import the necessary visualization and numerical computing modules, and configure Jupyter to display the charts inline:

PYTHON
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import randint
%matplotlib inline

Line Plots

Line plots track values over a continuous axis. We will generate numerical inputs using NumPy to build our baseline coordinates.

Generating Test Data

Use the linspace() function to return 20 evenly spaced values between 1 and 10:

PYTHON
x = np.linspace(1, 10, 20)
x
OUTPUT
array([ 1.        ,  1.47368421,  1.94736842,  2.42105263,  2.89473684,
        3.36842105,  3.84210526,  4.31578947,  4.78947368,  5.26315789,
        5.73684211,  6.21052632,  6.68421053,  7.15789474,  7.63157895,
        8.10526316,  8.57894737,  9.05263158,  9.52631579, 10.        ])

Generate 20 random integers between 1 and 50 using randint():

PYTHON
y = randint(1, 50, 20)
y
OUTPUT
array([43, 13, 39, 35, 14, 31, 36, 17, 27, 36, 15, 47, 12, 36,  6, 20, 19,
       17, 29, 36])

Verify the size of the random array:

PYTHON
y.size
OUTPUT
20

Inspect the first ten attributes and functions available within the PyPlot module:

PYTHON
dir(plt)[:10]
OUTPUT
['Annotation', 'Arrow', 'Artist', 'AutoLocator', 'Axes', 'Button', 'Circle', 'Figure', 'FigureCanvasBase', 'FixedFormatter']

Functional PyPlot Line Plots

Plot the unsorted random values along the default index x-axis:

PYTHON
plt.plot(y)

The resulting chart connects the random values in their generated sequence:

Line plot of unsorted random integers

Sort the random integers in ascending order to make the trend line readable:

PYTHON
y = np.sort(y)
print(y)
OUTPUT
[ 6 12 13 14 15 17 17 19 20 27 29 31 35 36 36 36 36 39 43 47]

Plot the sorted values:

PYTHON
plt.plot(y)

The sorted line plot displays a steady upward curve:

Line plot of sorted random integers

Labels and Title

Plot y against x explicitly, set the line color to green, and add labels and a title:

PYTHON
plt.plot(x, y, color = 'g')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.title('Random Plot')
plt.show()

The labeled chart displays the sorted relationship between x and y:

Green line plot with custom labels and title

Common Plot Types

Matplotlib provides several functions for common statistical chart types.

Scatter and Bar Plots

Use the scatter() function to display individual observations as points without connecting lines:

PYTHON
plt.scatter(x, y)

The scatter plot shows the data points distributed along the coordinate axes:

Scatter plot of x vs y coordinates

Create discrete categories and plot them as vertical bars using the bar() function:

PYTHON
b = [10, 20, 3, 4, 5]
a = ['a', 'b', 'c', 'd', 'e']
plt.bar(a, b)

The bar plot compares the values across the five categories:

Bar chart comparing values across five categorical bins

Histograms and Box Plots

Generate a list of 10 random samples from a range of 1 to 10,000:

PYTHON
from random import sample
data = sample(range(1, 10000), 10)
data
OUTPUT
[5768, 405, 2213, 7584, 5100, 1136, 7028, 1777, 3683, 4265]

Plot the sampled data as a histogram, adjusting the bar widths to 80% of the bin width:

PYTHON
plt.hist(data, rwidth=0.8)

The histogram aggregates the observations into frequency bins:

Histogram showing distribution of sampled values

Box plots show the five-number summary of a distribution, mapping the minimum, lower quartile (), median, upper quartile (), and maximum.

The box plot diagram below details how these metrics partition a distribution:

Box plot anatomy diagram detailing minimum, lower quartile, median, upper quartile, maximum, and IQR

Generate normal distribution samples with different standard deviations and plot them as box plots:

PYTHON
data = [np.random.normal(0, std, 100) for std in range(1,3)]
plt.boxplot(data, vert = True, patch_artist= True)
plt.show()

The box plots compare the spreads and outlier points of the two normal distributions:

Box plots comparing two normal distributions with different standard deviations

Subplots

Subplots allow you to arrange multiple coordinate charts within a single figure canvas.

Functional Subplots

Use plt.subplot(rows, cols, index) to split the canvas and active different subplots:

PYTHON
plt.subplot(1, 2, 1)
plt.plot(x, y, 'ro', markersize = 5)

plt.subplot(1, 2, 2)
y2 = y*x
plt.plot(x, y2, 'b*')

The layout displays red circles on the left and blue stars on the right:

Two side-by-side subplots displaying red circles and blue stars

Object-Oriented Subplots

The object-oriented interface separates the overall Figure canvas from the individual Axes coordinates. Create a single subplot layout:

PYTHON
fig, ax = plt.subplots()
ax.plot(x, y, markersize = 12, linewidth = 3, color = '#005425')

The object-oriented plotting call returns a clean green trend line:

Line plot created using the object-oriented API

Add custom inset axes by specifying relative coordinates [left, bottom, width, height] within the figure:

PYTHON
fig = plt.figure()
ax1 = fig.add_axes([0, 0, 1, 1])
ax2 = fig.add_axes([0.1, 0.6, 0.4, 0.3])

ax1.plot(x, y, 'r')
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_title('Y Plot')

ax2.plot(x, y2, 'g')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_title('Y2 Plot')

The main y-axis (red) contains a smaller, green inset plot (ax2) positioned in its upper-left quadrant:

Main line plot with a smaller inset plot overlaid in the corner

Generate a grid of subplots and access individual cells using index offsets:

PYTHON
fig, ax = plt.subplots(1,2)

ax[0].plot(x, y, 'b')

ax[1].plot(x, y, 'r')

The side-by-side subplots show the blue and red line plots:

Two side-by-side subplots displaying blue and red line charts

For larger layouts, loop through the axes array and adjust coordinates dynamically:

PYTHON
fig, ax = plt.subplots(1, 2)
col = ['r', 'g']
data = [y, y2]

for i, axes in enumerate(ax):
    axes.plot(x, data[i], col[i])

fig.tight_layout()

Using tight_layout() adjusts the margins between the green and red subplots to prevent overlapping:

Loop-generated subplots with overlapping margins resolved

Configure custom dimensions, DPI resolution, legends, and save the figure:

PYTHON
fig, ax = plt.subplots(figsize = (8,4), dpi = 100)

ax.plot(x, y, 'r', label = 'y')
ax.plot(x, y2, 'b', label = 'y*x')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Random Number Plot')
ax.legend(loc = 0)
fig.savefig('random file.png', dpi = 100)

The resulting chart overlays both trend lines and places the legend at the optimal location:

Overlaid line plots with custom legend and dimensions

Axis Controls

You can set custom limits, scale types, and tick values for each axes object.

Axis Limits

Use set_xlim() and set_ylim() to focus on specific coordinate ranges:

PYTHON
fig, ax = plt.subplots(1, 3, figsize = (12, 4))

ax[0].plot(x, y, x, y2)

ax[1].plot(x, y**2, 'k')
ax[1].set_ylim([0, 500])

ax[2].plot(x, y, x, y2)
ax[2].set_ylim([0, 100])
ax[2].set_xlim([1 ,4])

The subplots show the original range, a vertically capped curve, and a zoomed-in coordinates window:

Three subplots demonstrating different axis limit configurations

Axis Scales

Change scale types (e.g., to a logarithmic scale) using set_yscale():

PYTHON
fig, ax = plt.subplots(1, 2, figsize= (10, 4))
ax[0].plot(x, y, x, y2)

ax[1].plot(x, np.exp(x))
ax[1].set_yscale('log')
fig.tight_layout()

The log-scale subplot linearizes the exponential values along the y-axis:

Subplots comparing linear scale vs logarithmic y-axis scale

Custom Ticks and Formatting

Specify custom tick coordinates and labels, using raw strings for LaTeX mathematical notation:

PYTHON
fig, ax = plt.subplots(figsize = (10,5))
ax.plot(x, y2)
ax.set_xticks([1 , 3, 5, 10])
ax.set_xticklabels([r'a', r'b', r'$\gamma$', r'$\delta$'], fontsize=18)

ax.set_yticks([0, 100, 500])

The custom plot places labels and Greek letters at the tick marks:

Line plot with customized tick positions and Greek mathematical labels

Import the ticker module to configure locator and formatter classes:

PYTHON
from matplotlib import ticker

Apply scientific notation to tick values using a ScalarFormatter:

PYTHON
fig, ax = plt.subplots()
ax.plot(x, y2)
ax.set_title('Scientific Notation')

formatter = ticker.ScalarFormatter(useMathText=True)
formatter.set_scientific(True)
formatter.set_powerlimits((-1, 2))
ax.yaxis.set_major_formatter(formatter)

The y-axis formats the tick labels using scientific notation ():

Line plot displaying y-axis tick values formatted in scientific notation

Conclusion

In this tutorial, you explored Matplotlib's layout and customization pipeline. You built line, scatter, bar, histogram, and box plots, and configured subplots, inset axes, log scales, custom ticks, and scientific formatting.

Key takeaways:

  • PyPlot vs. Object-Oriented: The functional plt interface is useful for quick plotting, while the object-oriented API (fig, ax) is preferred for complex, multi-panel layouts.
  • Custom Insets: You can place coordinate axes anywhere on the canvas by specifying relative positioning values.
  • Tick Customization: Using locators and formatters allows you to configure Greek mathematical labels and scientific notation.
  • Layout Control: Functions like tight_layout() prevent overlapping text and keep label sizes legible across subplots.

Next steps:

Find this tutorial useful?

Subscribe to our YouTube channels for more practical production walk-throughs.

Discussion & Comments