Matplotlib Basics: Plots and Charts
Matplotlib is the most widely used visualization library in Python. It pairs naturally with NumPy arrays and pandas DataFrames, making it the standard tool for exploratory data analysis. This tutorial covers the essential plot types you will use every day.
Installing and Importing
pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
The pyplot module provides a MATLAB-style interface. Most examples use plt.subplots() which returns a figure and axis object — the modern, more flexible approach.
Line Plots
The most common plot type:
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
Customize the line with color, width, and style:
ax.plot(x, y, color='navy', linewidth=2, linestyle='--', label='sin(x)')
ax.set_title('Sine Wave')
ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.legend()
ax.grid(True, alpha=0.3)
Key parameters: color, linewidth, linestyle (solid, dashed, dotted), marker (o, s, ^ for points on the line).
Scatter Plots
Scatter plots show relationships between two variables:
np.random.seed(42)
x = np.random.randn(100)
y = 2 * x + np.random.randn(100) * 0.5
fig, ax = plt.subplots()
ax.scatter(x, y, alpha=0.6, edgecolors='white', linewidth=0.5, c='steelblue')
ax.set_title('Linear Relationship with Noise')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
alpha controls transparency — essential when plotting many overlapping points. c sets color.
Bar Charts
Compare categorical data:
languages = ['Python', 'Rust', 'Go', 'TypeScript', 'Java']
scores = [92, 78, 85, 88, 74]
fig, ax = plt.subplots()
bars = ax.bar(languages, scores, color=['#3572A5', '#dea584', '#00add8', '#3178c6', '#b07219'])
ax.set_ylabel('Popularity Score')
ax.set_title('Language Popularity')
# Add value labels on bars
for bar, score in zip(bars, scores):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1,
str(score), ha='center', fontsize=10)
plt.tight_layout()
plt.show()
Horizontal bars use barh. Grouped bars require multiple bar calls with offset.
Histograms
Show the distribution of numerical data:
data = np.random.randn(1000)
fig, ax = plt.subplots()
ax.hist(data, bins=40, edgecolor='black', alpha=0.75, color='slategray')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
ax.set_title('Normal Distribution Sample')
plt.show()
bins controls the number of bars. Too few hides structure; too many creates noise.
Saving Figures
Save to file before plt.show():
fig, ax = plt.subplots()
ax.plot(x, y)
fig.savefig('plot.png', dpi=300, bbox_inches='tight')
fig.savefig('plot.pdf', bbox_inches='tight')
Use PNG for raster images, PDF or SVG for vector graphics that scale without losing quality. dpi=300 is standard for print. bbox_inches='tight' trims excess whitespace.
Multiple Subplots
Show several plots in one figure:
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# Flatten the 2D array for easy indexing
axes = axes.flatten()
x = np.linspace(0, 10, 100)
axes[0].plot(x, np.sin(x), color='blue')
axes[0].set_title('Sine')
axes[1].plot(x, np.cos(x), color='red')
axes[1].set_title('Cosine')
axes[2].plot(x, x**2, color='green')
axes[2].set_title('Quadratic')
np.random.seed(0)
axes[3].scatter(np.random.randn(50), np.random.randn(50), alpha=0.6)
axes[3].set_title('Scatter')
plt.tight_layout()
plt.show()
figsize sets width and height in inches. subplots(2, 2) creates a 2x2 grid.
Common Customizations
Every plot benefits from labels and a title:
ax.set_xlabel('Time (seconds)')
ax.set_ylabel('Amplitude')
ax.set_title('Signal Over Time')
Control axis limits:
ax.set_xlim(0, 100)
ax.set_ylim(-1.5, 1.5)
Log scale axes:
ax.set_xscale('log')
ax.set_yscale('log')
Add a horizontal or vertical reference line:
ax.axhline(y=0, color='black', linewidth=0.8, linestyle='--')
ax.axvline(x=50, color='gray', linewidth=0.8)
matplotlib vs Seaborn
Matplotlib gives you full control. Seaborn builds on it with prettier defaults:
import seaborn as sns
sns.set_style("whitegrid")
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
Seaborn automatically improves colors, fonts, and spacing. Use matplotlib for custom work, seaborn for quick exploratory plots.
See Also
- /tutorials/scientific-python/numpy-getting-started/ — NumPy arrays feed into matplotlib
- /tutorials/scientific-python/pandas-getting-started/ — pandas DataFrames work directly with matplotlib
- /guides/matplotlib-subplots/ — more on arranging multiple plots
Saving Figures
Save plots as image files for reports and presentations:
fig, ax = plt.subplots()
ax.plot(x, y)
fig.savefig("plot.png", dpi=300, bbox_inches='tight')
fig.savefig("plot.pdf") # vector format for publications
The dpi argument controls resolution — 300 for print, 150 for web. Use bbox_inches='tight' to trim excess whitespace. PNG for raster output, PDF for vector graphics that scale without quality loss.