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:
- Import
matplotlib.pyplot(conventionally asplt). - Call a plotting function (
plt.plot(),plt.bar(), etc.) with your data. - Call decorator functions to add titles, axis labels, legends, and so on.
- Call
plt.show()to display the figure, orplt.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 matplotlibVerify the installation by importing it:
import matplotlib
print(matplotlib.__version__) # e.g. 3.9.0Creating 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=90rotates 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 coloro— circle marker--— dashed line
Common format string codes:
| Code | Meaning | Code | Meaning |
|---|---|---|---|
b | blue | - | solid line |
g | green | -- | dashed line |
r | red | -. | dash-dot line |
k | black | : | dotted line |
o | circle | s | square |
^ | 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()beforeplt.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 memoryOverlapping subplots. Calling plt.tight_layout() or plt.subplots_adjust() after creating all subplots fixes overlapping titles and tick labels.
Summary
| Chart type | Function | Best used for |
|---|---|---|
| Line plot | plt.plot() | Trends over ordered data |
| Bar chart | plt.bar() / plt.barh() | Comparing discrete categories |
| Pie chart | plt.pie() | Part-to-whole composition |
| Scatter plot | plt.scatter() | Relationship between two variables |
| Subplots | plt.subplots() | Multiple charts in one figure |
Related Chapters
- Matplotlib Introduction — overview of the library and its components
- Matplotlib Get Started — installation and your first plot
- Matplotlib Line Plots — line styles, markers, and multi-series plots in depth
- Matplotlib Bar Charts — vertical, horizontal, and stacked bars
- Matplotlib Pie Charts — exploding slices, custom colors, and donut charts
- Matplotlib Histograms — distribution plots and bin control
- Matplotlib Scatter Plot — bubble charts and color-mapped scatter
- Matplotlib Subplots — advanced multi-panel layouts
- Matplotlib Labels — titles, axis labels, annotations, and text
- Matplotlib Grid — grid lines and tick customization
- Matplotlib Markers — marker styles, sizes, and edge colors