Python · 第 3 篇
数据可视化实战
一图胜千言。 你用 Pandas 算出的增长率、转化率、留存率,如果只是数字铺在表格里,业务方看了可能一脸茫然。但换成一张趋势图、一张漏斗图,结论瞬间清晰。本篇教你用 Python 制作专业级的数据分析图表。
Python 可视化库全景
| 库 | 特点 | 适用场景 |
|---|---|---|
| Matplotlib | 底层绑定,灵活度最高 | 自定义需求高的图表、论文配图 |
| Seaborn | 基于 Matplotlib,自带统计功能 | 探索性分析、统计图表 |
| Plotly | 交互式图表,支持拖拽缩放 | 数据报告、网页展示 |
| Pyecharts | 百度 ECharts 的 Python 封装 | 需要中文友好的交互式图表 |
本篇重点讲 Matplotlib + Seaborn,它们是数据分析师最常用的组合。
环境准备
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体(解决中文乱码问题)
plt.rcParams["font.sans-serif"] = ["SimHei", "Arial Unicode MS", "Noto Sans CJK SC"]
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
# 设置 Seaborn 主题
sns.set_theme(style="whitegrid", font_scale=1.1)
常见坑:Matplotlib 默认不支持中文,如果图表出现方框乱码,一定要先设置中文字体。Mac 用户推荐
Arial Unicode MS,Windows 用户用SimHei,Linux 用Noto Sans CJK SC。
Matplotlib 基础
第一张图:折线图
# 模拟某电商平台近 7 天的 DAU 数据
dates = pd.date_range("2024-03-01", periods=7, freq="D")
dau = [85000, 82000, 91000, 88000, 95000, 110000, 105000]
plt.figure(figsize=(10, 5))
plt.plot(dates, dau, marker="o", color="#4F46E5", linewidth=2, markersize=6)
plt.title("近 7 日 DAU 趋势", fontsize=16, fontweight="bold")
plt.xlabel("日期")
plt.ylabel("日活跃用户数")
plt.grid(True, alpha=0.3)
# 标注最大值
max_idx = dau.index(max(dau))
plt.annotate(
f"峰值: {max(dau):,}",
xy=(dates[max_idx], max(dau)),
xytext=(dates[max_idx], max(dau) + 3000),
fontsize=11,
ha="center",
arrowprops=dict(arrowstyle="->", color="red"),
color="red",
)
plt.tight_layout()
plt.savefig("dau_trend.png", dpi=150)
plt.show()
柱状图:渠道对比
channels = ["微信", "抖音", "小红书", "百度SEM", "自然搜索"]
orders = [4200, 3800, 2100, 1500, 3200]
colors = ["#4F46E5", "#06B6D4", "#F59E0B", "#EF4444", "#10B981"]
plt.figure(figsize=(10, 5))
bars = plt.bar(channels, orders, color=colors, edgecolor="white", linewidth=0.8)
# 在柱子上方标注数值
for bar, val in zip(bars, orders):
plt.text(
bar.get_x() + bar.get_width() / 2,
bar.get_height() + 50,
f"{val:,}",
ha="center",
fontsize=11,
fontweight="bold",
)
plt.title("各渠道月订单量对比", fontsize=16, fontweight="bold")
plt.ylabel("订单量")
plt.ylim(0, max(orders) * 1.15)
plt.tight_layout()
plt.show()
饼图 / 环形图:占比分析
labels = ["微信", "抖音", "小红书", "百度SEM", "自然搜索"]
sizes = [4200, 3800, 2100, 1500, 3200]
colors = ["#4F46E5", "#06B6D4", "#F59E0B", "#EF4444", "#10B981"]
explode = [0.05, 0, 0, 0, 0] # 突出第一个扇区
fig, ax = plt.subplots(figsize=(8, 8))
wedges, texts, autotexts = ax.pie(
sizes,
labels=labels,
colors=colors,
explode=explode,
autopct="%1.1f%%",
startangle=90,
pctdistance=0.75,
wedgeprops=dict(width=0.45), # 环形图效果
)
ax.set_title("各渠道订单占比", fontsize=16, fontweight="bold")
plt.tight_layout()
plt.show()
子图组合:一页多图
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
# 子图 1:趋势
axes[0].plot(dates, dau, marker="o", color="#4F46E5")
axes[0].set_title("DAU 趋势")
axes[0].set_ylabel("DAU")
# 子图 2:渠道对比
axes[1].barh(channels, orders, color=colors)
axes[1].set_title("渠道订单量")
axes[1].set_xlabel("订单量")
# 子图 3:占比
axes[2].pie(sizes, labels=labels, colors=colors, autopct="%1.0f%%")
axes[2].set_title("渠道订单占比")
fig.suptitle("电商运营日报 - 2024.03.07", fontsize=18, fontweight="bold", y=1.02)
plt.tight_layout()
plt.show()
Seaborn 进阶可视化
Seaborn 在 Matplotlib 的基础上提供了更高级的统计图表,代码更简洁,默认配色更美观。
分布图:了解数据分布
# 模拟用户消费金额数据
np.random.seed(42)
spend_data = pd.DataFrame({
"消费金额": np.concatenate([
np.random.normal(200, 80, 500), # 普通用户
np.random.normal(800, 200, 100), # 高消费用户
]),
"用户类型": ["普通用户"] * 500 + ["VIP用户"] * 100,
})
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 直方图 + KDE 核密度估计
sns.histplot(data=spend_data, x="消费金额", hue="用户类型", kde=True, ax=axes[0])
axes[0].set_title("用户消费金额分布")
# 箱线图——发现异常值
sns.boxplot(data=spend_data, x="用户类型", y="消费金额", palette="Set2", ax=axes[1])
axes[1].set_title("不同用户类型消费金额箱线图")
plt.tight_layout()
plt.show()
热力图:相关性分析
# 模拟电商指标数据
np.random.seed(42)
metrics = pd.DataFrame({
"UV": np.random.randint(5000, 20000, 30),
"加购数": np.random.randint(500, 3000, 30),
"订单数": np.random.randint(100, 800, 30),
"GMV": np.random.randint(30000, 150000, 30),
"退货数": np.random.randint(10, 100, 30),
"客单价": np.random.uniform(100, 500, 30),
})
# 计算相关系数矩阵
corr = metrics.corr()
plt.figure(figsize=(8, 6))
sns.heatmap(
corr,
annot=True, # 显示数值
fmt=".2f", # 保留 2 位小数
cmap="RdYlBu_r", # 配色方案
center=0,
square=True,
linewidths=0.5,
)
plt.title("电商核心指标相关性矩阵", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.show()
业务洞察:热力图可以快速发现哪些指标之间强相关。例如 UV 和订单数正相关(流量越大、订单越多),而退货数和客单价可能负相关(高客单价商品用户更谨慎、退货率更低)。
散点图 + 回归线:关系分析
plt.figure(figsize=(8, 6))
sns.regplot(
data=metrics,
x="UV",
y="订单数",
scatter_kws={"alpha": 0.6, "s": 60},
line_kws={"color": "red"},
)
plt.title("UV 与订单数的关系", fontsize=14, fontweight="bold")
plt.xlabel("UV(访问用户数)")
plt.ylabel("订单数")
plt.tight_layout()
plt.show()
分面图:多维度对比
# 模拟多渠道多月份数据
np.random.seed(42)
multi_data = pd.DataFrame({
"月份": np.tile(["1月", "2月", "3月", "4月", "5月", "6月"], 3),
"渠道": np.repeat(["微信", "抖音", "小红书"], 6),
"GMV": np.random.randint(50000, 200000, 18),
"订单数": np.random.randint(200, 1000, 18),
})
g = sns.FacetGrid(multi_data, col="渠道", height=4, aspect=1.2)
g.map_dataframe(sns.barplot, x="月份", y="GMV", palette="viridis")
g.set_titles("{col_name}")
g.set_axis_labels("月份", "GMV (元)")
g.fig.suptitle("各渠道月度 GMV 对比", fontsize=16, fontweight="bold", y=1.03)
plt.tight_layout()
plt.show()
业务场景实战
场景一:漏斗图
电商转化漏斗是最常见的分析需求之一:
# 漏斗数据
stages = ["浏览商品", "加入购物车", "进入结算", "提交订单", "支付成功"]
values = [100000, 35000, 18000, 12000, 9500]
rates = [f"{v/values[0]*100:.1f}%" for v in values]
fig, ax = plt.subplots(figsize=(10, 6))
colors = plt.cm.Blues(np.linspace(0.3, 0.9, len(stages)))
for i, (stage, val, rate) in enumerate(zip(stages, values, rates)):
width = val / values[0]
left = (1 - width) / 2
ax.barh(len(stages) - 1 - i, width, left=left, height=0.6, color=colors[i])
ax.text(0.5, len(stages) - 1 - i, f"{stage}\n{val:,} ({rate})",
ha="center", va="center", fontsize=11, fontweight="bold")
ax.set_xlim(0, 1)
ax.set_yticks([])
ax.set_xticks([])
ax.set_title("电商转化漏斗", fontsize=16, fontweight="bold")
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["left"].set_visible(False)
plt.tight_layout()
plt.show()
场景二:留存率曲线
# 模拟 7 日留存率数据
days = list(range(1, 8))
retention_organic = [45, 32, 28, 25, 23, 22, 21]
retention_paid = [38, 22, 16, 13, 11, 10, 9]
plt.figure(figsize=(10, 5))
plt.plot(days, retention_organic, marker="o", linewidth=2, label="自然流量", color="#10B981")
plt.plot(days, retention_paid, marker="s", linewidth=2, label="付费流量", color="#EF4444")
plt.fill_between(days, retention_organic, alpha=0.1, color="#10B981")
plt.fill_between(days, retention_paid, alpha=0.1, color="#EF4444")
plt.title("新用户 7 日留存率对比", fontsize=16, fontweight="bold")
plt.xlabel("注册后第 N 天")
plt.ylabel("留存率 (%)")
plt.legend()
plt.xticks(days)
plt.ylim(0, 55)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
业务洞察:自然流量的留存率显著高于付费流量,说明自然流量的用户质量更高。付费流量在第 3 天后留存快速衰减,可以考虑在第 2-3 天推送优惠券来提升留存。
场景三:同比环比分析
months = ["1月", "2月", "3月", "4月", "5月", "6月"]
this_year = [120, 135, 118, 142, 156, 149]
last_year = [98, 105, 110, 115, 128, 135]
x = np.arange(len(months))
width = 0.35
fig, ax1 = plt.subplots(figsize=(12, 6))
# 柱状图:绝对值
bars1 = ax1.bar(x - width/2, last_year, width, label="2023年", color="#94A3B8", alpha=0.8)
bars2 = ax1.bar(x + width/2, this_year, width, label="2024年", color="#4F46E5", alpha=0.9)
ax1.set_ylabel("GMV (万元)", fontsize=12)
ax1.set_xticks(x)
ax1.set_xticklabels(months)
ax1.legend(loc="upper left")
# 折线图:同比增长率(双轴)
ax2 = ax1.twinx()
yoy_growth = [(t - l) / l * 100 for t, l in zip(this_year, last_year)]
ax2.plot(x, yoy_growth, color="#EF4444", marker="D", linewidth=2, label="同比增长率")
ax2.set_ylabel("同比增长率 (%)", fontsize=12, color="#EF4444")
ax2.legend(loc="upper right")
plt.title("月度 GMV 同比分析", fontsize=16, fontweight="bold")
plt.tight_layout()
plt.show()
图表美化清单
制作正式的分析报告时,注意以下细节:
| 要素 | 建议 |
|---|---|
| 标题 | 简洁明了,包含指标名称和时间范围 |
| 坐标轴标签 | 说明单位(元/万元/%/人) |
| 图例 | 有多组数据时必须添加 |
| 数据标签 | 关键数值直接标注在图上 |
| 配色 | 同系列用同一色系,对比用互补色,不超过 5 种颜色 |
| 网格线 | 降低透明度,辅助读数但不抢眼 |
| 导出分辨率 | dpi=150 以上,用于报告或 PPT |
| 图片比例 | 趋势图宽扁(16:9),对比图适当宽(4:3) |
# 导出高质量图片
plt.savefig("chart.png", dpi=200, bbox_inches="tight", facecolor="white")
小结
本篇覆盖了数据分析师最常用的可视化技能:
- Matplotlib 基础:折线图、柱状图、饼图、子图组合
- Seaborn 进阶:分布图、热力图、散点回归图、分面图
- 业务场景:转化漏斗、留存曲线、同比环比分析
- 美化技巧:字体、配色、标注、导出
学会了数据处理和可视化,下一篇我们将在 实战:数据清洗与分析 中把所有技能串起来,完成一个从原始数据到分析报告的完整项目。