Machine Learning: Matplotlib与Seaborn可视化 — 数据模式可视化完全指南
一张好图胜过千行数据——可视化是发现数据模式的第一步。
1. 你将学到
- Matplotlib基础:figure/axes/subplots体系、折线图、柱状图、散点图
- Seaborn高级图表:分布图histplot、箱线图boxplot、热力图heatmap
- 多子图与样式定制:sns.set_theme、调色板、中文显示配置
- 电商数据可视化实战:月度销售额趋势、品类占比、用户RFM分布
- 可视化图表选择决策:根据数据类型选择最佳图表
2. 一个产品经理的真实故事
(1) 痛点:表格数据看不出趋势和异常
Bob把SalesPredict的月度销售报表发给团队——50行Excel数据,没人能快速看出哪个品类在下滑、哪些月份有异常波动。Alice的美国数据趋势和中国数据完全不同,但只看数字很难发现。数据埋在表格里,关键洞察被淹没。
(2) 可视化的解法
一张折线图立刻暴露:Electronics品类Q3有明显下滑趋势;一张热力图揭示广告费和销售额的相关性远超预期。
PYTHON
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) 收益:5分钟发现关键业务洞察
Bob用可视化替代纯表格后,5分钟就发现了Q3 Electronics品类15%的下滑趋势,及时调整了广告策略挽回约200 thousand USD的潜在损失。
3. Matplotlib基础
(1) Figure/Axes体系
Matplotlib采用两层结构:Figure(画布)包含一个或多个Axes(绘图区)。
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]
▶ 示例:创建基础折线图
PYTHON
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)
输出:
TEXT
📖 仅展示
# 执行成功
(2) 常用图表类型
▶ 示例:柱状图与散点图
PYTHON
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)
输出:
TEXT
📖 仅展示
# 执行成功
| 图表类型 | 最佳场景 | Matplotlib函数 |
|---|---|---|
| 折线图 | 时间趋势 | ax.plot() |
| 柱状图 | 类别比较 | ax.bar() / ax.barh() |
| 散点图 | 两变量关系 | ax.scatter() |
| 饼图 | 占比分布 | ax.pie() |
| 直方图 | 单变量分布 | ax.hist() |
4. Seaborn高级图表
Seaborn构建在Matplotlib之上,提供更高级的统计图表和更美观的默认样式。
(1) 分布图
▶ 示例:订单金额分布分析
PYTHON
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)
输出:
TEXT
📖 仅展示
# 执行成功
(2) 热力图
▶ 示例:特征相关性热力图
PYTHON
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)
输出:
TEXT
📖 仅展示
# 执行成功
(3) 多子图布局
▶ 示例:SalesPredict 4维度分析面板
PYTHON
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)
输出:
TEXT
📖 仅展示
# 执行成功
5. 样式定制与图表选择
(1) Seaborn主题与调色板
PYTHON
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
| 主题 | 背景 | 网格 | 适用场景 |
|---|---|---|---|
| darkgrid | 深色 | 有 | 数据密集型 |
| whitegrid | 白色 | 有 | 学术报告 |
| dark | 深色 | 无 | 演示文稿 |
| white | 白色 | 无 | 论文 |
| ticks | 白色 | 无 | 极简风格 |
(2) 图表选择决策
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]
▶ 示例:中文显示配置
PYTHON
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)")
输出:
TEXT
📖 仅展示
# 执行成功
❓ 常见问题
Q Matplotlib和Seaborn该用哪个?
A 日常分析用Seaborn(更简洁美观),需要精细控制用Matplotlib。Seaborn的底层就是Matplotlib,两者可以混用。
Q 图表中文乱码怎么解决?
A 设置
plt.rcParams["font.sans-serif"]为中文字体。但推荐用英文标签,避免跨平台字体问题。Q savefig保存图片模糊怎么办?
A 设置dpi参数:
plt.savefig("fig.png", dpi=150)。论文用300+,网页用100-150。矢量图用.svg或.pdf格式。Q 如何选择合适的图表类型?
A 看数据类型和目的——时间趋势用折线图,类别比较用柱状图,分布用直方图/箱线图,两变量关系用散点图/热力图。
Q Seaborn的hue参数是什么?
A hue按指定列分组着色。如
sns.scatterplot(data=df, x="ad_spend", y="revenue", hue="category")会为每个品类用不同颜色。Q 子图间距太紧怎么办?
A 用
plt.tight_layout()自动调整,或用plt.subplots_adjust(hspace=0.3, wspace=0.3)手动控制间距。📖 小节
- Matplotlib的Figure/Axes体系是所有图表的基础:Figure是画布,Axes是绘图区
- Seaborn提供更高级的统计图表:histplot(KDE分布)、boxplot(箱线)、heatmap(相关热力图)
- 多子图布局用
plt.subplots(nrows, ncols)创建,统一管理多个图表 - 图表选择遵循数据类型:时间→折线、类别→柱状、分布→直方图、关系→散点/热力图
- 中文显示需配置字体,但推荐英文标签确保跨平台兼容
- seaborn.set_theme()一键设定风格,调色板选择考虑色盲友好
📝 作业
- 基础题(难度⭐):用Matplotlib绘制一条折线图,展示12个月的销售额趋势,添加标题和轴标签。提示:参考第3节的折线图示例。
- 进阶题(难度⭐⭐):用Seaborn绘制一个2x2子图:折线图(趋势)、柱状图(品类比较)、箱线图(分布)、热力图(相关性),使用SalesPredict模拟数据。提示:
plt.subplots(2,2)+sns.xxx(ax=axes[i,j])。 - 挑战题(难度⭐⭐⭐):创建一个交互式仪表盘概念——绘制月度Revenue趋势图,在图上用不同颜色标注"促销月"和"普通月",并添加注释说明促销效果。提示:用
ax.axvspan()标注区间,ax.annotate()添加注释。