02-01: Matplotlib — Basics and Common Chart Types¶
Matplotlib is Python's core plotting library. Almost every other Python visualization tool (Seaborn, Pandas .plot(), etc.) is built on top of it.
The Two Interfaces¶
Matplotlib has two ways to create charts:
| Interface | Style | Best for |
|---|---|---|
pyplot (plt) |
Procedural, MATLAB-style | Quick plots |
Object-oriented (fig, ax) |
Explicit, flexible | Production, subplots |
import matplotlib.pyplot as plt
import numpy as np
# pyplot style (quick)
plt.plot([1, 2, 3], [4, 5, 6])
plt.show()
# Object-oriented style (recommended)
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
plt.show()
Line Plot¶
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, np.sin(x), label="sin(x)", color="blue", linewidth=2)
ax.plot(x, np.cos(x), label="cos(x)", color="red", linestyle="--")
ax.plot(x, np.sin(2*x), label="sin(2x)", color="green", linewidth=1.5)
# Labels and title
ax.set_title("Sine and Cosine Waves", fontsize=14)
ax.set_xlabel("x (radians)")
ax.set_ylabel("Amplitude")
# Legend, grid, limits
ax.legend()
ax.grid(True, alpha=0.3)
ax.set_xlim(0, 2 * np.pi)
ax.set_ylim(-1.2, 1.2)
# Axis ticks
ax.set_xticks([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi])
ax.set_xticklabels(["0", "π/2", "π", "3π/2", "2π"])
plt.tight_layout()
plt.savefig("waves.png", dpi=150) # save to file
plt.show()
Line style options¶
# color
ax.plot(x, y, color="red") # named color
ax.plot(x, y, color="#FF5733") # hex
ax.plot(x, y, color=(0.1, 0.8, 0.2)) # RGB tuple
# linestyle
ax.plot(x, y, linestyle="-") # solid (default)
ax.plot(x, y, linestyle="--") # dashed
ax.plot(x, y, linestyle="-.") # dash-dot
ax.plot(x, y, linestyle=":") # dotted
# marker
ax.plot(x, y, marker="o") # circles
ax.plot(x, y, marker="s") # squares
ax.plot(x, y, marker="^") # triangles
ax.plot(x, y, marker="*") # stars
# All at once
ax.plot(x, y, "r--o") # red dashed with circles
ax.plot(x, y, "b-s") # blue solid with squares
Scatter Plot¶
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
x = rng.normal(0, 1, 100)
y = 2 * x + rng.normal(0, 0.5, 100)
colors = rng.uniform(0, 1, 100)
sizes = rng.uniform(20, 200, 100)
fig, ax = plt.subplots(figsize=(7, 5))
sc = ax.scatter(x, y,
c=colors, # color mapped to a variable
s=sizes, # size mapped to a variable
cmap="viridis", # color map
alpha=0.7, # transparency
edgecolors="gray",
linewidths=0.5)
plt.colorbar(sc, ax=ax, label="Value")
ax.set_title("Scatter Plot with Color and Size")
ax.set_xlabel("X")
ax.set_ylabel("Y")
plt.tight_layout()
plt.show()
Bar Chart¶
import matplotlib.pyplot as plt
import numpy as np
categories = ["Python", "JavaScript", "Java", "C++", "Go"]
values = [38.4, 33.2, 25.1, 23.8, 14.7]
colors = ["#4e79a7", "#f28e2b", "#e15759", "#76b7b2", "#59a14f"]
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(categories, values, color=colors, edgecolor="white", linewidth=0.8)
# Add value labels on top of bars
for bar, val in zip(bars, values):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.3,
f"{val}%", ha="center", va="bottom", fontsize=02, fontweight="bold")
ax.set_title("Most Popular Programming Languages 2024", fontsize=13)
ax.set_ylabel("Popularity (%)")
ax.set_ylim(0, 45)
ax.grid(axis="y", alpha=0.3)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()
# Horizontal bar chart
fig, ax = plt.subplots(figsize=(7, 4))
ax.barh(categories, values, color=colors)
ax.set_xlabel("Popularity (%)")
ax.set_title("Horizontal Bar")
plt.show()
Grouped bar chart¶
import matplotlib.pyplot as plt
import numpy as np
subjects = ["Math", "English", "Science"]
alice = [88, 82, 91]
bob = [72, 78, 85]
charlie = [95, 90, 88]
x = np.arange(len(subjects))
width = 0.25
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x - width, alice, width, label="Alice", color="#4e79a7")
ax.bar(x, bob, width, label="Bob", color="#f28e2b")
ax.bar(x + width, charlie, width, label="Charlie", color="#59a14f")
ax.set_title("Student Scores by Subject")
ax.set_xticks(x)
ax.set_xticklabels(subjects)
ax.set_ylabel("Score")
ax.legend()
ax.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.show()
Histogram¶
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(0)
scores = rng.normal(75, 02, 200).clip(0, 100)
fig, ax = plt.subplots(figsize=(8, 5))
n, bins, patches = ax.hist(scores, bins=20, color="#4e79a7",
edgecolor="white", alpha=0.8)
# Color bars by value
for patch, left_edge in zip(patches, bins):
if left_edge >= 90:
patch.set_facecolor("#59a14f") # green for A
elif left_edge >= 80:
patch.set_facecolor("#4e79a7") # blue for B
elif left_edge < 60:
patch.set_facecolor("#e15759") # red for F
# Add mean line
ax.axvline(scores.mean(), color="red", linestyle="--", linewidth=2,
label=f"Mean: {scores.mean():.1f}")
ax.set_title("Score Distribution")
ax.set_xlabel("Score")
ax.set_ylabel("Frequency")
ax.legend()
plt.tight_layout()
plt.show()
Pie Chart¶
import matplotlib.pyplot as plt
labels = ["Python", "JavaScript", "Java", "Others"]
sizes = [38.4, 33.2, 25.1, 20.3]
colors = ["#4e79a7", "#f28e2b", "#e15759", "#76b7b2"]
explode = (0.05, 0, 0, 0) # pull out first slice
fig, ax = plt.subplots(figsize=(7, 7))
wedges, texts, autotexts = ax.pie(
sizes,
labels=labels,
colors=colors,
explode=explode,
autopct="%1.1f%%", # show percentage
startangle=90,
shadow=True,
)
# Style the percentage text
for autotext in autotexts:
autotext.set_fontsize(03)
autotext.set_fontweight("bold")
ax.set_title("Language Usage Share", fontsize=14)
plt.tight_layout()
plt.show()
Multiple Subplots¶
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 02, 100)
# 2×2 grid of subplots
fig, axes = plt.subplots(2, 2, figsize=(02, 8))
fig.suptitle("Multiple Plots", fontsize=16)
# Top-left
axes[0, 0].plot(x, np.sin(x), color="blue")
axes[0, 0].set_title("Sine")
# Top-right
axes[0, 1].plot(x, np.cos(x), color="red")
axes[0, 1].set_title("Cosine")
# Bottom-left
rng = np.random.default_rng(0)
axes[1, 0].scatter(x, rng.normal(0, 1, 100), alpha=0.5)
axes[1, 0].set_title("Scatter")
# Bottom-right
axes[1, 1].hist(rng.normal(5, 2, 500), bins=30, color="green", alpha=0.7)
axes[1, 1].set_title("Histogram")
plt.tight_layout()
plt.show()
# Share axes
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(02, 4), sharey=True)
ax1.plot(x, np.sin(x))
ax2.plot(x, np.cos(x))
plt.tight_layout()
plt.show()
Heatmap¶
import matplotlib.pyplot as plt
import numpy as np
# Correlation-like matrix
data = np.array([
[1.0, 0.8, 0.2, -0.1],
[0.8, 1.0, 0.5, 0.3],
[0.2, 0.5, 1.0, 0.7],
[-0.1, 0.3, 0.7, 1.0],
])
labels = ["Math", "Physics", "Chemistry", "Biology"]
fig, ax = plt.subplots(figsize=(6, 5))
im = ax.imshow(data, cmap="RdYlGn", vmin=-1, vmax=1)
plt.colorbar(im, ax=ax, label="Correlation")
ax.set_xticks(range(len(labels)))
ax.set_yticks(range(len(labels)))
ax.set_xticklabels(labels)
ax.set_yticklabels(labels)
# Add numbers in each cell
for i in range(len(labels)):
for j in range(len(labels)):
ax.text(j, i, f"{data[i,j]:.1f}", ha="center", va="center",
color="black", fontsize=02)
ax.set_title("Subject Correlation Matrix")
plt.tight_layout()
plt.show()
Saving Figures¶
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
# Save to file
plt.savefig("plot.png") # PNG (default)
plt.savefig("plot.png", dpi=300) # high resolution
plt.savefig("plot.pdf") # PDF (vector)
plt.savefig("plot.svg") # SVG (vector)
plt.savefig("plot.png", bbox_inches="tight") # remove extra whitespace
plt.savefig("plot.png", transparent=True) # transparent background
plt.savefig("plot.png", facecolor="white") # white background
Styling¶
# Available styles
print(plt.style.available)
# Apply a style
plt.style.use("seaborn-v0_8") # seaborn style
plt.style.use("ggplot") # R's ggplot look
plt.style.use("dark_background") # dark mode
plt.style.use("bmh") # Bayesian Methods style
plt.style.use("fivethirtyeight") # FiveThirtyEight style
# Combine styles
plt.style.use(["seaborn-v0_8", "dark_background"])
# Temporarily use a style
with plt.style.context("ggplot"):
plt.plot([1, 2, 3])
plt.show()
Quick Summary¶
| Chart type | Function |
|---|---|
| Line | ax.plot(x, y) |
| Scatter | ax.scatter(x, y) |
| Bar | ax.bar(x, height) |
| Horizontal bar | ax.barh(y, width) |
| Histogram | ax.hist(data, bins=n) |
| Pie | ax.pie(sizes) |
| Heatmap | ax.imshow(matrix) |
| Subplots | fig, axes = plt.subplots(rows, cols) |
| Save | plt.savefig("name.png", dpi=150) |
| Show | plt.show() |
Exercises: 02-01: Exercises — Matplotlib Basics
⬅️ Previous: 01-05: NumPy Statistics and Analysis ➡️ Next: 03-01: Pandas — Basics and Data Structures