Pandas 与 Matplotlib / Seaborn 进阶可视化
承接《Pandas 与 NumPy 结合使用》,本篇聚焦进阶可视化,不再只讲基础绘图,重点讲解 Pandas 数据对接 Matplotlib、Seaborn 的工作流、多子图、样式美化、分组绘图、双轴、中文、导出、图表联动、大数据绘图优化,保持系列教程统一风格。
前置导入
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 示例数据
df = pd.DataFrame({
"region": ["华东","华东","华南","华南","华北","华北","华东","华南","华北","华东"],
"cate": ["手机","电脑","手机","电脑","手机","电脑","手机","电脑","手机","电脑"],
"sales": [1200, 800, 1500, 950, 1100, 780, 1350, 1020, 960, 1420],
"profit": [180, 120, 220, 140, 160, 110, 195, 150, 132, 176]
})
print(df)
一、基础协作关系
- Pandas 内置
.plot():底层封装 Matplotlib,语法极简,适合快速探索; - Seaborn:专门面向统计图表,接收 Pandas DataFrame 作为 data 参数,自动处理分组、调色;
- Matplotlib:底层画布、坐标轴、子图、字体、布局、导出控制;
标准工作流:Pandas 做数据清洗、分组、透视 → 传给 seaborn / plt 绘图 → matplotlib 精细调整样式。
统一设置(中文、负号,必加)
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid") # seaborn全局样式
二、Pandas plot 进阶用法(基于matplotlib)
df.plot() 返回 Axes 对象,可以继续用 matplotlib 接口修改,这是进阶关键。
# 基础,返回ax
ax = df.plot(kind="bar", x="region", y="sales", figsize=(10,4))
ax.set_title("区域销售额")
ax.set_xlabel("区域")
ax.set_ylabel("销售额")
plt.show()
2.1 多子图 subplots
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
df.groupby("region")["sales"].sum().plot(kind="bar", ax=ax1, title="销售额")
df.groupby("region")["profit"].sum().plot(kind="line", marker="o", ax=ax2, title="利润")
plt.tight_layout() # 自动调整间距,防止标签重叠
plt.show()
重点:
ax=ax1把绘图绑定到指定子图,是多图排版核心。
2.2 双Y轴(twinx)
适合量级差距很大的两个指标,销售额&利润率
g_df = df.groupby("region").agg(sales=("sales","sum"), profit_rate=("profit","sum"))
ax1 = g_df["sales"].plot(kind="bar", color="#4472C4", figsize=(10,5))
ax2 = ax1.twinx()
g_df["profit_rate"].plot(kind="line", color="#ED7D31", marker="o", ax=ax2)
ax1.set_ylabel("销售额")
ax2.set_ylabel("利润")
plt.show()
2.3 分组绘图 + 堆叠柱状图
pivot_df = df.pivot_table(index="region", columns="cate", values="sales", aggfunc="sum")
ax = pivot_df.plot(kind="bar", stacked=True, figsize=(9,5))
ax.legend(title="品类")
plt.show()
三、Seaborn 进阶:接收Pandas DataFrame
seaborn 优势:直接传入 data=df,通过 x/y/hue 指定字段,不用手动整理透视表。
3.1 分组柱状图 hue
plt.figure(figsize=(10,5))
sns.barplot(data=df, x="region", y="sales", hue="cate", errorbar=None)
plt.title("各区域分品类销售额")
plt.show()
hue:分组配色,对应Pandas的分类字段errorbar=None:关闭默认误差棒(业务报表常用)
3.2 箱线图 boxplot(分布探查)
plt.figure(figsize=(8,5))
sns.boxplot(data=df, x="region", y="sales", hue="cate")
plt.show()
3.3 热力图 heatmap(相关性矩阵/透视表)
corr = df[["sales","profit"]].corr()
plt.figure(figsize=(5,4))
sns.heatmap(corr, annot=True, cmap="Blues", fmt=".2f")
plt.show()
透视表热力图(业务高频)
pivot = df.pivot_table(index="region", columns="cate", values="sales", aggfunc="sum")
plt.figure(figsize=(6,4))
sns.heatmap(pivot, annot=True, fmt="g", cmap="OrRd")
plt.show()
3.4 散点图 + 拟合线 regplot
plt.figure(figsize=(7,5))
sns.regplot(data=df, x="sales", y="profit")
plt.show()
四、FacetGrid 分面绘图(Seaborn高阶)
自动按字段切分多个子图,等价循环分组绘图,适合做多维度对比
g = sns.FacetGrid(data=df, col="cate", height=4)
g.map(sns.barplot, "region", "sales", errorbar=None)
g.set_titles("品类:{col_name}")
plt.show()
col按列分面;row按行分面;hue颜色分组
五、图表美化进阶
- 调色盘
# seaborn调色板
sns.set_palette("Set2")
# 自定义颜色列表
colors = ["#1f77b4","#ff7f0e"]
- 图例、网格、边框
ax.legend(loc="upper right", bbox_to_anchor=(1.2,1)) # 图例放到图外侧
ax.grid(axis="y", alpha=0.3)
sns.despine() # 移除上、右边框
- 刻度旋转,防止文字重叠
plt.xticks(rotation=30)
六、导出高清图片
plt.savefig("chart.png", dpi=300, bbox_inches="tight")
# bbox_inches="tight" 自动裁掉多余空白,避免图例被截断
plt.close() # 释放画布,循环绘图必须加,防止内存暴涨
支持格式:png、jpg、pdf、svg矢量图
七、大数据绘图优化(非常重要)
当数据上万行以上,直接绘图卡顿、内存高:
- 采样:
df.sample(frac=0.1, random_state=42)抽样后再画散点图 - 聚合:先 groupby 汇总,再绘图,不要直接画原始明细
- 避免 sns.scatterplot 画百万点,改用 hexbin 热力分箱图
# 示例:hexbin 替代海量散点
fig, ax = plt.subplots()
ax.hexbin(df["sales"], df["profit"], gridsize=15, cmap="Blues")
plt.colorbar(ax.collections[0])
plt.show()
八、循环批量绘图模板(业务报表)
region_list = df["region"].unique()
for r in region_list:
sub_df = df[df["region"] == r]
plt.figure(figsize=(7,4))
sns.barplot(data=sub_df, x="cate", y="sales", errorbar=None)
plt.title(f"{r} 销售明细")
plt.savefig(f"{r}_sale.png", dpi=300, bbox_inches="tight")
plt.close()
九、Pandas + Matplotlib + Seaborn 选型建议
- 快速看趋势、简单折线/柱状:Pandas
.plot() - 统计分布、箱线、分组对比、热力图:Seaborn
- 精细排版、复杂多子图、自定义标注、双轴:Matplotlib底层控制
十、高频坑清单
- 中文乱码:忘记设置
font.sans-serif;Linux服务器字体缺失,需要预装中文字体 - 循环绘图不写
plt.close(),画布堆积,内存泄漏 - 图例、标题被截断:保存时不加
bbox_inches="tight" - seaborn 传入数组,不使用data参数,hue不方便绑定字段
- 大数据直接绘制散点图,渲染极慢,优先聚合/抽样/hexbin
- 多个子图忘记
tight_layout(),标签重叠 - twinx 双轴图例默认分开,需要手动合并图例
十一、综合实战模板
def plot_region_sales(df, save_path=None):
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
sns.set_style("whitegrid")
fig, ax = plt.subplots(figsize=(10,5))
sns.barplot(data=df, x="region", y="sales", hue="cate", ax=ax, errorbar=None)
ax.set_title("区域-品类销售额")
ax.set_xlabel("区域")
ax.set_ylabel("销售额")
sns.despine()
if save_path:
plt.savefig(save_path, dpi=300, bbox_inches="tight")
plt.close()
else:
plt.show()
plot_region_sales(df)
十二、速查表
| 需求 | 方案 |
|---|---|
| 快速绘图,少代码 | df.plot(kind=”xxx”, ax=ax) |
| 分组统计图表、hue配色 | seaborn barplot / boxplot |
| 相关性矩阵 | sns.heatmap |
| 按维度自动切分多图 | FacetGrid |
| 双Y轴 | ax.twinx() |
| 高清导出 | savefig(dpi=300, bbox_inches=”tight”) |
| 百万级散点 | hexbin 分箱热力图 |
0 条笔记