Matplotlib & Seaborn Visualization
A good chart is worth a thousand rows of data — visualization is the first step in discovering patterns.
1. What You'll Learn
- Matplotlib fundamentals: the figure/axes/subplots system, line charts, bar charts, scatter plots
- Seaborn advanced charts: distribution plots (histplot), box plots, heatmaps
- Multi-subplot layouts and style customization: sns.set_theme, color palettes, CJK font configuration
- E-commerce data visualization in practice: monthly revenue trends, category share, user RFM distribution
- Chart selection decisions: choosing the best chart type for your data
2. A Real Story from a Product Manager
(1) The Pain Point: Trends and Anomalies Are Invisible in Tabular Data
Bob sent the SalesPredict monthly sales report to his team — 50 rows of Excel data, and nobody could quickly tell which category was declining or which months had abnormal fluctuations. Alice's US data trends were completely different from the China data, but staring at raw numbers made it nearly impossible to spot the difference. The data was buried in spreadsheets, and the key insights were drowned out.
(2) The Visualization Solution
A single line chart instantly revealed a clear downward trend in the Electronics category during Q3; a heatmap showed that the correlation between ad spend and revenue far exceeded expectations.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
# Quick visualization reveals hidden patterns
df = pd.read_csv("monthly_sales.csv")
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
df.plot(x="month", y="revenue", ax=axes[0], title="Revenue Trend")
sns.heatmap(df.corr(numeric_only=True), annot=True, ax=axes[1])
plt.tight_layout()
plt.savefig("sales_overview.png", dpi=150)
(3) The Payoff: Key Business Insights in 5 Minutes
After replacing raw tables with visualizations, Bob spotted the 15% decline in the Electronics category during Q3 within 5 minutes. He adjusted the advertising strategy in time, recovering approximately 200 thousand USD in potential losses.
3. Matplotlib Fundamentals
(1) The Figure/Axes System
Matplotlib uses a two-layer architecture: a Figure (canvas) contains one or more Axes (plotting areas).
graph TB
FIG[Figure - Canvas] --> AX1[Axes 1<br/>Subplot 1]
FIG --> AX2[Axes 2<br/>Subplot 2]
AX1 --> LINE[Line Chart]
AX2 --> BAR[Bar Chart]
▶ Example: Creating a Basic Line Chart
import matplotlib.pyplot as plt
# Monthly revenue data (thousand USD)
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
revenue = [120, 135, 150, 142, 160, 175, 180, 190, 195, 200, 220, 250]
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(months, revenue, marker="o", linewidth=2, color="#2196F3")
ax.set_title("Monthly Revenue Trend", fontsize=14)
ax.set_xlabel("Month")
ax.set_ylabel("Revenue (thousand USD)")
ax.grid(True, alpha=0.3)
ax.fill_between(months, revenue, alpha=0.1, color="#2196F3")
# Annotate peak
peak_idx = revenue.index(max(revenue))
ax.annotate(f"Peak: {max(revenue)}k", xy=(peak_idx, max(revenue)),
xytext=(peak_idx-2, max(revenue)+15),
arrowprops=dict(arrowstyle="->", color="red"))
plt.tight_layout()
plt.savefig("revenue_trend.png", dpi=150)
Output:
# Executed successfully
(2) Common Chart Types
▶ Example: Bar Chart and Scatter Plot
import matplotlib.pyplot as plt
import numpy as np
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Bar chart: category revenue
categories = ["Electronics", "Clothing", "Food", "Books", "Home"]
revenue = [2500, 1450, 900, 700, 4000]
colors = ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF"]
axes[0].barh(categories, revenue, color=colors)
axes[0].set_title("Revenue by Category")
axes[0].set_xlabel("Revenue (thousand USD)")
# Scatter plot: ad spend vs revenue
np.random.seed(42)
ad_spend = np.random.uniform(10, 100, 50)
sales = 50 + 0.8 * ad_spend + np.random.normal(0, 10, 50)
axes[1].scatter(ad_spend, sales, alpha=0.6, color="#2196F3", edgecolors="white")
axes[1].set_title("Ad Spend vs Revenue")
axes[1].set_xlabel("Ad Spend (thousand USD)")
axes[1].set_ylabel("Revenue (thousand USD)")
# Add trend line
z = np.polyfit(ad_spend, sales, 1)
p = np.poly1d(z)
axes[1].plot(ad_spend, p(ad_spend), "r--", alpha=0.8, linewidth=2)
plt.tight_layout()
plt.savefig("bar_scatter.png", dpi=150)
Output:
# Executed successfully
| Chart Type | Best Use Case | Matplotlib Function |
|---|---|---|
| Line chart | Time trends | ax.plot() |
| Bar chart | Category comparison | ax.bar() / ax.barh() |
| Scatter plot | Two-variable relationship | ax.scatter() |
| Pie chart | Proportional distribution | ax.pie() |
| Histogram | Single-variable distribution | ax.hist() |
4. Seaborn Advanced Charts
Seaborn is built on top of Matplotlib, providing higher-level statistical charts and more polished default styles.
(1) Distribution Plots
▶ Example: Order Amount Distribution Analysis
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
# Generate order amount data
rng = np.random.default_rng(42)
orders_normal = rng.normal(150, 50, 1000)
orders_normal = orders_normal[orders_normal > 0] # Remove negatives
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Histogram with KDE
sns.histplot(orders_normal, bins=30, kde=True, ax=axes[0], color="#2196F3")
axes[0].set_title("Order Amount Distribution")
axes[0].set_xlabel("Amount (USD)")
# Box plot by category
categories = rng.choice(["Electronics", "Clothing", "Food"], 500)
amounts = np.where(categories == "Electronics",
rng.normal(300, 80, 500),
np.where(categories == "Clothing",
rng.normal(120, 40, 500),
rng.normal(50, 20, 500)))
amounts = np.clip(amounts, 1, None)
data = {"category": categories, "amount": amounts}
sns.boxplot(data=data, x="category", y="amount", ax=axes[1], palette="Set2")
axes[1].set_title("Order Amount by Category")
plt.tight_layout()
plt.savefig("distribution.png", dpi=150)
Output:
# Executed successfully
(2) Heatmaps
▶ Example: Feature Correlation Heatmap
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Simulate SalesPredict feature correlations
np.random.seed(42)
n = 200
ad_spend = np.random.uniform(10, 100, n)
traffic = ad_spend * 1.2 + np.random.normal(0, 15, n)
conversion = traffic * 0.03 + np.random.normal(0, 0.5, n)
revenue = conversion * 150 + np.random.normal(0, 500, n)
customer_age = np.random.uniform(18, 65, n)
df = pd.DataFrame({
"ad_spend": ad_spend,
"traffic": traffic,
"conversion_rate": conversion,
"revenue": revenue,
"customer_age": customer_age,
})
corr = df.corr()
fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r",
center=0, vmin=-1, vmax=1, ax=ax,
square=True, linewidths=0.5)
ax.set_title("Feature Correlation Heatmap")
plt.tight_layout()
plt.savefig("correlation_heatmap.png", dpi=150)
Output:
# Executed successfully
(3) Multi-Subplot Layouts
▶ Example: SalesPredict 4-Dimension Analysis Panel
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
rng = np.random.default_rng(42)
df = pd.DataFrame({
"date": pd.date_range("2024-01-01", periods=90),
"revenue": rng.normal(5000, 1000, 90).cumsum(),
"category": rng.choice(["Elec", "Cloth", "Food"], 90),
"orders": rng.integers(50, 200, 90),
})
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# (1) Revenue trend
axes[0, 0].plot(df["date"], df["revenue"], color="#2196F3")
axes[0, 0].set_title("Daily Revenue Trend")
# (2) Category distribution
cat_rev = df.groupby("category")["revenue"].sum()
axes[0, 1].pie(cat_rev, labels=cat_rev.index, autopct="%1.1f%%")
# (3) Orders distribution
sns.histplot(df["orders"], bins=20, kde=True, ax=axes[1, 0], color="#4CAF50")
axes[1, 0].set_title("Orders Distribution")
# (4) Revenue vs Orders
axes[1, 1].scatter(df["orders"], df["revenue"], alpha=0.5, c="#FF5722")
axes[1, 1].set_title("Revenue vs Orders")
plt.tight_layout()
plt.savefig("dashboard.png", dpi=150)
Output:
# Executed successfully
5. Style Customization and Chart Selection
(1) Seaborn Themes and Color Palettes
import seaborn as sns
# Set global theme
sns.set_theme(style="whitegrid", palette="muted", font_scale=1.2)
# Available themes: darkgrid, whitegrid, dark, white, ticks
# Available palettes: deep, muted, pastel, bright, dark, colorblind
| Theme | Background | Grid | Best For |
|---|---|---|---|
| darkgrid | Dark | Yes | Data-dense displays |
| whitegrid | White | Yes | Academic reports |
| dark | Dark | No | Presentations |
| white | White | No | Papers |
| ticks | White | No | Minimalist style |
(2) Chart Selection Decision Guide
graph TB
DATA[Data Type] --> CAT[Categorical]
DATA --> NUM[Numerical]
DATA --> TIME[Time Series]
CAT --> COMP[Comparison<br/>Bar Chart]
CAT --> PART[Part of Whole<br/>Pie / Stacked Bar]
NUM --> DIST[Distribution<br/>Histogram / KDE / Box]
NUM --> REL[Relationship<br/>Scatter / Heatmap]
TIME --> TREND[Trend<br/>Line Chart]
TIME --> SEA[Seasonality<br/>Seasonal Plot]
▶ Example: CJK Font Configuration
import matplotlib.pyplot as plt
# Method 1: Use SimHei font (Windows)
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False
# Method 2: Use English labels (recommended for i18n)
# Keep all labels in English to avoid font issues across platforms
fig, ax = plt.subplots()
ax.set_title("Monthly Sales Report") # English for compatibility
ax.set_xlabel("Month")
ax.set_ylabel("Revenue (thousand USD)")
Output:
# Executed successfully
❓ FAQ
plt.rcParams["font.sans-serif"] to a CJK font. However, using English labels is recommended to avoid cross-platform font issues.plt.savefig("fig.png", dpi=150). Use 300+ for papers, 100–150 for web. For vector graphics, use .svg or .pdf format.hue parameter in Seaborn do?hue groups and colors data by a specified column. For example, sns.scatterplot(data=df, x="ad_spend", y="revenue", hue="category") assigns a different color to each category.plt.tight_layout() for automatic adjustment, or plt.subplots_adjust(hspace=0.3, wspace=0.3) for manual spacing control.📖 Summary
- Matplotlib's Figure/Axes system is the foundation of all charts: Figure is the canvas, Axes is the plotting area
- Seaborn provides higher-level statistical charts: histplot (KDE distribution), boxplot (box plot), heatmap (correlation heatmap)
- Multi-subplot layouts are created with
plt.subplots(nrows, ncols)for unified management of multiple charts - Chart selection follows data type: time → line, category → bar, distribution → histogram, relationship → scatter/heatmap
- CJK display requires font configuration, but English labels are recommended for cross-platform compatibility
seaborn.set_theme()sets the style in one line; choose colorblind-friendly palettes when possible
📝 Exercises
- Basic (Difficulty ⭐): Use Matplotlib to draw a line chart showing 12 months of sales trends. Add a title and axis labels. Hint: refer to the line chart example in Section 3.
- Intermediate (Difficulty ⭐⭐): Use Seaborn to create a 2x2 subplot panel: line chart (trend), bar chart (category comparison), box plot (distribution), and heatmap (correlation), using simulated SalesPredict data. Hint:
plt.subplots(2,2)+sns.xxx(ax=axes[i,j]). - Challenge (Difficulty ⭐⭐⭐): Create an interactive dashboard concept — plot a monthly revenue trend chart, highlight "promotion months" and "regular months" in different colors, and add annotations explaining the promotion effects. Hint: use
ax.axvspan()to shade regions andax.annotate()to add annotations.
← Previous: Pandas Data Processing | Next: Getting Started with Scikit-learn →