W3docs

Python Matplotlib Plotting: A Comprehensive Guide

Learn how to create and customize line plots, bar charts, pie charts, scatter plots, and subplots in Python with Matplotlib, with clear examples.

Matplotlib is the most widely used data-visualization library in Python. This guide explains how to create the most common plot types — line plots, bar charts, pie charts, scatter plots, and subplots — and how to customize them with labels, colors, legends, and layout controls. It assumes you have already installed Matplotlib and can run Python scripts locally.

What Is Matplotlib Plotting?

Matplotlib's pyplot module provides a MATLAB-style interface that lets you build plots step by step: create a figure, add data, add labels, then display or save the result. Every plot follows the same pattern:

  1. Import matplotlib.pyplot (conventionally as plt).
  2. Call a plotting function (plt.plot(), plt.bar(), etc.) with your data.
  3. Call decorator functions to add titles, axis labels, legends, and so on.
  4. Call plt.show() to display the figure, or plt.savefig() to write it to disk.

Understanding this sequence makes it straightforward to switch between plot types and combine them into more complex figures.

Installing Matplotlib

If you have not yet installed Matplotlib, run the following command in your terminal:

pip install matplotlib

Verify the installation by importing it:

import matplotlib
print(matplotlib.__version__)  # e.g. 3.9.0

Creating a Line Plot

A line plot is the default chart type and is ideal for showing trends over time or any ordered sequence.

import matplotlib.pyplot as plt

# Data
years = [2015, 2016, 2017, 2018, 2019, 2020]
sales = [100, 150, 200, 250, 300, 350]

# Plot
plt.plot(years, sales)

# Labels and title
plt.xlabel("Year")
plt.ylabel("Sales (units)")
plt.title("Annual Sales")

plt.show()

plt.plot(x, y) draws a continuous line connecting each (x, y) pair. The x-axis shows years and the y-axis shows sales figures, revealing the upward trend at a glance.

Plotting Multiple Lines

To compare two datasets on the same axes, call plt.plot() twice before plt.show(). Use the label parameter and plt.legend() to identify each line:

import matplotlib.pyplot as plt

years = [2018, 2019, 2020, 2021, 2022]
product_a = [120, 145, 170, 210, 260]
product_b = [90, 115, 140, 165, 195]

plt.plot(years, product_a, label="Product A")
plt.plot(years, product_b, label="Product B")

plt.xlabel("Year")
plt.ylabel("Revenue ($k)")
plt.title("Revenue by Product")
plt.legend()

plt.show()

Matplotlib automatically assigns different colors to each series. Calling plt.legend() adds a key that maps colors to labels.

Creating a Bar Chart

Bar charts compare discrete categories. Use plt.bar() for vertical bars and plt.barh() for horizontal bars.

import matplotlib.pyplot as plt

countries = ["USA", "China", "Japan", "Germany", "UK"]
gdp = [21.44, 14.14, 5.15, 4.17, 2.62]

plt.bar(countries, gdp, color="steelblue")

plt.xlabel("Country")
plt.ylabel("GDP (USD trillions)")
plt.title("Top 5 Economies by GDP")

plt.show()

Each bar's height represents the GDP value. The color parameter accepts any named CSS color, hex string, or RGB tuple.

Grouped Bar Charts

When you need to compare multiple categories side by side, shift the bar positions manually using range() and a width offset:

import matplotlib.pyplot as plt

categories = ["Q1", "Q2", "Q3", "Q4"]
team_a = [30, 45, 38, 52]
team_b = [25, 40, 35, 48]

x = range(len(categories))
width = 0.35

plt.bar([i - width / 2 for i in x], team_a, width=width, label="Team A")
plt.bar([i + width / 2 for i in x], team_b, width=width, label="Team B")

plt.xticks(x, categories)
plt.xlabel("Quarter")
plt.ylabel("Sales")
plt.title("Quarterly Sales by Team")
plt.legend()

plt.show()

plt.xticks(x, categories) replaces the numeric tick positions with the actual quarter names.

Creating a Pie Chart

Pie charts show how parts make up a whole. Use them sparingly — they work best with five or fewer slices that add up to 100 %.

import matplotlib.pyplot as plt

brands = ["Samsung", "Apple", "Huawei", "Xiaomi", "Others"]
market_share = [19.2, 15.9, 14.6, 10.2, 40.1]

plt.pie(
    market_share,
    labels=brands,
    autopct="%1.1f%%",   # show percentage inside each slice
    startangle=90,       # rotate so the first slice starts at the top
)

plt.title("Smartphone Market Share")

plt.show()
  • autopct="%1.1f%%" prints the percentage to one decimal place inside each slice.
  • startangle=90 rotates the chart so the first slice starts at 12 o'clock, which is easier to read.

Note: The market-share figures above are approximate and are used here for illustration only.

Creating a Scatter Plot

Scatter plots reveal the relationship between two continuous variables. Each point represents one observation.

import matplotlib.pyplot as plt

hours_studied = [1, 2, 3, 4, 5, 6, 7, 8]
exam_scores   = [45, 52, 60, 65, 72, 78, 85, 90]

plt.scatter(hours_studied, exam_scores, color="coral", edgecolors="black", s=80)

plt.xlabel("Hours Studied")
plt.ylabel("Exam Score")
plt.title("Study Time vs. Exam Score")

plt.show()

The s parameter controls marker size in points squared. edgecolors="black" adds an outline to each point, making them easier to distinguish when points overlap.

For a deeper dive, see the Matplotlib Scatter Plot chapter.

Customizing Plot Appearance

Matplotlib exposes fine-grained control over nearly every visual element.

Colors, Markers, and Line Styles

Pass a format string as the third argument to plt.plot() to set marker style, line style, and color in one step:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]

plt.plot(x, y, "ro--")   # red circles, dashed line
plt.xlabel("x")
plt.ylabel("y")
plt.title("Custom Style")
plt.show()

The format string "ro--" combines:

  • r — red color
  • o — circle marker
  • -- — dashed line

Common format string codes:

CodeMeaningCodeMeaning
bblue-solid line
ggreen--dashed line
rred-.dash-dot line
kblack:dotted line
ocirclessquare
^triangle up*star

You can also pass keyword arguments for more control:

plt.plot(x, y, color="#2196f3", linewidth=2, linestyle="--", marker="o", markersize=8)

Figure Size and DPI

Set the figure dimensions (in inches) before plotting by calling plt.figure():

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 5), dpi=100)   # 1000×500 pixels

x = [1, 2, 3, 4, 5]
y = [1, 4, 9, 16, 25]

plt.plot(x, y)
plt.title("Wide Figure")
plt.show()

figsize=(width, height) takes inches. dpi (dots per inch) controls pixel density — 100 dpi is fine for screen; 300 dpi is typical for print.

Adding a Grid

A grid makes it easier to read off values:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [3, 7, 2, 9, 4]

plt.plot(x, y, marker="o")
plt.grid(True, linestyle="--", alpha=0.7)
plt.title("Plot with Grid")
plt.show()

alpha=0.7 makes the grid lines semi-transparent so they do not overpower the data. See the Matplotlib Grid chapter for more options.

Creating Subplots

Subplots let you display multiple charts in one figure, which is useful for comparing different views of the same dataset.

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y1 = [2, 4, 6, 8, 10]
y2 = [1, 4, 9, 16, 25]
y3 = [5, 3, 7, 2, 8]
y4 = [10, 7, 4, 5, 6]

fig, axes = plt.subplots(2, 2, figsize=(10, 8))

axes[0][0].plot(x, y1, "b-o")
axes[0][0].set_title("Linear")

axes[0][1].plot(x, y2, "r--s")
axes[0][1].set_title("Quadratic")

axes[1][0].bar(x, y3, color="green")
axes[1][0].set_title("Bar Chart")

axes[1][1].scatter(x, y4, color="purple", s=80)
axes[1][1].set_title("Scatter")

plt.tight_layout()   # prevent overlapping labels
plt.show()

plt.subplots(rows, cols) returns a Figure object and a 2-D array of Axes objects. Working with individual Axes objects (e.g., axes[0][0].plot(...)) is the preferred approach for multi-plot layouts because it gives you independent control over each panel. plt.tight_layout() automatically adjusts spacing so that titles and labels do not overlap.

See the Matplotlib Subplots chapter for advanced layout options.

Saving a Plot to a File

plt.savefig() writes the current figure to disk. It infers the file format from the extension:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 4, 6, 8, 10]

plt.plot(x, y, marker="o")
plt.title("Saved Plot")

plt.savefig("my_plot.png", dpi=150, bbox_inches="tight")
  • Supported formats include .png, .jpg, .svg, and .pdf.
  • bbox_inches="tight" trims whitespace around the figure so nothing is clipped.
  • Always call plt.savefig() before plt.show()plt.show() clears the figure state.

Common Pitfalls

plt.show() clears the figure. If you call plt.savefig() after plt.show(), you will save a blank image. Always save first, show second.

Running in non-interactive environments. In scripts, plt.show() opens a GUI window and blocks until it is closed. In Jupyter notebooks, use %matplotlib inline at the top so plots render inline. In headless servers (CI, Docker), switch to a non-interactive backend: import matplotlib; matplotlib.use("Agg") before importing pyplot.

Forgetting to close figures. Each call to plt.figure() opens a new figure in memory. In loops that generate many plots, close each one with plt.close() to avoid memory exhaustion.

import matplotlib.pyplot as plt

for i in range(10):
    plt.plot([1, 2, 3], [i, i * 2, i * 3])
    plt.savefig(f"plot_{i}.png")
    plt.close()   # release memory

Overlapping subplots. Calling plt.tight_layout() or plt.subplots_adjust() after creating all subplots fixes overlapping titles and tick labels.

Summary

Chart typeFunctionBest used for
Line plotplt.plot()Trends over ordered data
Bar chartplt.bar() / plt.barh()Comparing discrete categories
Pie chartplt.pie()Part-to-whole composition
Scatter plotplt.scatter()Relationship between two variables
Subplotsplt.subplots()Multiple charts in one figure
Was this page helpful?