Four production-ready charts: a line chart, bar chart, scatter plot, and histogram — all with proper labels, clean styling, and saved as high-res image files.
Setup and the Figure/Axes Model
Install matplotlib and seaborn:
$ pip install matplotlib seaborn pandas numpyThe most important thing to understand in matplotlib is the object hierarchy: Figure is the entire canvas. Axes is one individual plot on that canvas. A Figure can contain multiple Axes.
import matplotlib.pyplot as plt
import numpy as np
# Create a Figure and one Axes object
fig, ax = plt.subplots(figsize=(10, 6))
# Data
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
revenue = [42000, 51000, 48000, 63000, 71000, 68000]
# Plot
ax.plot(months, revenue, color="#1e3a5f", linewidth=2, marker="o")
# Labels — always include these
ax.set_title("Monthly Revenue H1 2025", fontsize=16, pad=20)
ax.set_xlabel("Month")
ax.set_ylabel("Revenue ($)")
plt.tight_layout()
plt.savefig("revenue_chart.png", dpi=150, bbox_inches="tight")
plt.show()Bar Charts, Scatter Plots, and Histograms
The three other chart types you'll use constantly:
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Bar Chart
categories = ["Product A", "Product B", "Product C"]
values = [340, 280, 195]
axes[0].bar(categories, values, color=["#1e3a5f", "#c4873e", "#4a7fa5"])
axes[0].set_title("Product Sales")
# Scatter Plot
x = np.random.normal(50, 15, 100)
y = x * 0.8 + np.random.normal(0, 8, 100)
axes[1].scatter(x, y, alpha=0.6, color="#1e3a5f")
axes[1].set_title("Correlation Plot")
# Histogram
data = np.random.normal(75, 12, 500)
axes[2].hist(data, bins=20, color="#1e3a5f", edgecolor="white")
axes[2].set_title("Score Distribution")
plt.tight_layout()
plt.savefig("three_charts.png", dpi=150, bbox_inches="tight")Styling and Annotations
Default matplotlib charts look dated. Two changes make them look professional: a clean style and annotations that tell the story.
import matplotlib.pyplot as plt
import matplotlib.style as style
# Clean built-in style
style.use("seaborn-v0_8-whitegrid")
fig, ax = plt.subplots(figsize=(10, 6))
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
revenue = [42000, 51000, 48000, 63000, 71000, 68000]
ax.plot(months, revenue, color="#1e3a5f", linewidth=2.5, marker="o", markersize=8)
# Annotate the peak
peak_idx = revenue.index(max(revenue))
ax.annotate(
f"Peak: ${max(revenue):,}",
xy=(peak_idx, max(revenue)),
xytext=(peak_idx - 1, max(revenue) + 3000),
arrowprops={"arrowstyle": "->", "color": "#c4873e"},
fontsize=11, color="#c4873e", fontweight="bold"
)
ax.set_title("Monthly Revenue H1 2025", fontsize=16, pad=16)
plt.tight_layout()
plt.savefig("styled.png", dpi=150, bbox_inches="tight")What You Learned Today
- The Figure/Axes object model — always use fig, ax = plt.subplots() pattern
- Four core chart types: line, bar, scatter, histogram
- How to use plt.subplots() to create multi-chart layouts
- How to annotate charts to tell the story, not just display data
Go Further on Your Own
- Build a 2x2 grid of charts from a dataset of your choice: line, bar, scatter, and histogram in one figure
- Add a second line to your line chart showing a benchmark or prior year comparison, with a legend
- Modify the bar chart to use horizontal bars (barh) — which orientation works better for your data?
Nice work. Keep going.
Day 2 is ready when you are.
Continue to Day 2Want live instruction and hands-on projects? Join the AI bootcamp — 3 days, 5 cities.