Python Matplotlib绘图教程:折线图、散点图等数据可视化实战
针对初学与进阶开发者的 Python Matplotlib 实用数据可视化指南。系统拆解面向对象绘图机制,通过折线图、散点图及多维数据映射的完整代码实例,详解参数调优、样式配置及高频排坑方案。
一、Matplotlib 架构理解:为什么推荐面向对象接口
很多初学者在编写绘图脚本时习惯直接调用 plt.plot() 或 plt.scatter()。这种方式属于 MATLAB 风格的“状态机接口”(State-machine Interface),其特点是操作隐式:系统在后台记录当前“活动的画布”与“活动的坐标系”。当脚本只需绘制一张简单图表时,状态机非常快;但在处理多个子图、调整局部坐标轴刻度或嵌入外部应用时,状态机模式容易出现操作串位和状态丢失。
工业级数据分析与生产环境推荐采用面向对象接口(Object-Oriented API)。通过 fig, ax = plt.subplots() 显式创建画布容器(Figure)与坐标轴对象(Axes)。其中 Figure 代表整张图的画纸空间,包含尺寸、分辨率与背景色;Axes 则是具体承载数据点、刻度线、网格与图例的实际绘图区。所有绘图方法都绑定在 ax 对象上,调用关系透明,多子图独立管理互不干扰。
一个标准的面向对象绘图流程分为五个清晰步骤:
- 环境准备与配置:导入
matplotlib.pyplot,并统一指定中文显示字体与负号支持配置; - 创建画布与坐标系:显式调用
plt.subplots(figsize=(宽, 高))创建fig和ax实例; - 数据映射与绘制:在坐标轴对象上调用
ax.plot()、ax.scatter()等几何图形绘制函数; - 坐标轴与文本修饰:配置轴标签、主标题、参考网格(
ax.grid())及图例说明(ax.legend()); - 渲染展示或持久化导出:调用
plt.show()进行交互查看,或调用fig.savefig()导出高分辨率图片。
二、折线图实战:时序变化与连续趋势分析
折线图(Line Plot)主要用于展示连续型变量随时间或有序序列的变化规律。绘制折线图的核心在于让线条走势清晰、关键采样点醒目,且多条对比曲线之间具有显著的视觉区分度。
1. 核心参数与几何控制
在面向对象模式中,折线图通过 ax.plot(x, y, ...) 进行绘制。控制其外观的核心参数包括:
color:线条与标记的基准色彩,支持 16 进制颜色(如#6487A5)或标准色彩名称;linestyle:线型样式,常用实线'-'、虚线'--'、点划线'-.'与细点线':';linewidth:线条像素宽度,主趋势推荐2.0 ~ 2.5,次要辅助线推荐1.0 ~ 1.5;marker与markersize:采样节点标记符号(如圆点'o'、方块's'、三角'^'),让离散的数据观测点一目了然;label:数据序列的文本标识,后续调用ax.legend()时将以此为图例标题。
2. 完整实战代码:多产品月度业绩趋势对比
以下示例展示了 2026 年上半年两种业务产品的销售额对比。代码完整覆盖了中文字体注入、多线样式差异化、网格辅助与图例布局:
import matplotlib.pyplot as plt
# 1. 配置全局中文支持与负号正常显示
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False
# 2. 准备业务数据
months = ['1月', '2月', '3月', '4月', '5月', '6月']
sales_prod_a = [32.5, 45.0, 58.2, 51.0, 68.4, 79.8] # 单位:万元
sales_prod_b = [28.0, 31.5, 39.0, 44.5, 48.0, 53.2]
# 3. 创建画布与坐标系
fig, ax = plt.subplots(figsize=(8, 4.8), dpi=100)
# 4. 绘制对比折线
ax.plot(months, sales_prod_a,
color='#6487A5', linestyle='-', linewidth=2.2,
marker='o', markersize=6, label='核心产品 A')
ax.plot(months, sales_prod_b,
color='#C28B68', linestyle='--', linewidth=2.0,
marker='s', markersize=6, label='新兴产品 B')
# 5. 坐标轴与辅助信息修饰
ax.set_title('2026年上半年产品销售额趋势对比', fontsize=14, pad=14, fontweight='bold')
ax.set_xlabel('月份', fontsize=11, labelpad=8)
ax.set_ylabel('销售额 (万元)', fontsize=11, labelpad=8)
ax.set_ylim(20, 90)
# 开启轻量虚线网格,增强数值横向对比
ax.grid(True, linestyle='--', alpha=0.5)
# 添加图例说明
ax.legend(loc='upper left', frameon=True, facecolor='#FFFFFF', edgecolor='#CBD5E1')
# 6. 保存或展示
plt.tight_layout()
# fig.savefig('line_sales_trend.png', dpi=300, bbox_inches='tight')
plt.show()
三、散点图实战:相关性分析与四维数据编码
散点图(Scatter Plot)的核心价值在于研究两组连续数值变量之间的相关分布规律,例如观察身高与体重、广告投入与销售转化、或者发现聚类群体与异常离群点。在更高阶的数据分析场景中,散点图还能进一步扩展为“气泡图”,利用点的位置、尺寸、色彩同步表达多达 4 个维度的特征信息。
1. 四维通道映射规则
调用 ax.scatter(x, y, s, c, cmap, alpha, edgecolors) 时,各个参数承担着精确的数据通道分工:
- 通道 1 与 2(X, Y 坐标):定位平面的横纵空间坐标,直接反映两变量的正相关、负相关或非线性关系;
- 通道 3(点大小
s):将第三个数值特征映射为数据点的绘制面积(单位为点平方)。例如用圆圈大小代表企业规模或用户量; - 通道 4(色彩梯度
c与cmap):将第四个数值特征映射为连续颜色谱。通过fig.colorbar(scatter_obj)附带垂直色条,直观呈现数值高低区间; - 防重叠调优(
alpha与edgecolors):当样本量较多时,数据点极易相互重叠掩盖分布密度。设置alpha=0.6~0.75并给边缘加上edgecolors='#2C3E50',能让密集团内部的层叠层数清晰显现。
2. 完整实战代码:多门店客流、客单价与营收综合气泡图
import numpy as np
import matplotlib.pyplot as plt
# 保证中文正常输出
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False
# 模拟 50 家零售门店数据
np.random.seed(42)
daily_visitors = np.random.uniform(500, 3500, 50) # X: 日均客流 (人次)
avg_ticket_price = 120 + 0.03 * daily_visitors + np.random.normal(0, 20, 50) # Y: 客单价 (元)
store_area = np.random.uniform(80, 500, 50) # Size: 门店面积 (平米)
monthly_profit = (daily_visitors * avg_ticket_price * 0.25) / 1000 # Color: 月利润 (千元)
fig, ax = plt.subplots(figsize=(8.5, 5.2), dpi=100)
# 面积通过平方比例放大,适配散点图像素面积单位
bubble_sizes = store_area * 0.6
# 绘制散点图
sc = ax.scatter(daily_visitors, avg_ticket_price,
s=bubble_sizes,
c=monthly_profit,
cmap='viridis',
alpha=0.75,
edgecolors='#2C3E50',
linewidths=0.8)
# 添加颜色标尺 (Colorbar)
cbar = fig.colorbar(sc, ax=ax, pad=0.03)
cbar.set_label('月均净利润 (千元)', fontsize=10.5)
# 轴标签与标题
ax.set_title('50家试点门店客流、客单价、营业面积与利润分布分析', fontsize=13, fontweight='bold', pad=12)
ax.set_xlabel('日均进店人次 (X轴)', fontsize=11)
ax.set_ylabel('平均客单价 / 元 (Y轴)', fontsize=11)
ax.grid(True, linestyle=':', alpha=0.6)
plt.tight_layout()
plt.show()
四、进阶组合实战:散点观测值与拟合趋势线同图排版
在实际业务分析中,折线图与散点图往往不是孤立存在的。最常见的场景是:先用散点展示实验或采集到的实际离散样本,随后使用平滑折线绘制回归方程预测的拟合趋势线。二者在同一个 Axes 坐标系中叠加,既展示了底层数据的真实离散度,又交代了整体规律。
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False
# 构造模拟数据
x_sample = np.linspace(1, 10, 30)
noise = np.random.normal(0, 1.2, size=len(x_sample))
y_sample = 2.4 * x_sample + 3.0 + noise
# 拟合一次线性回归方程
slope, intercept = np.polyfit(x_sample, y_sample, 1)
x_line = np.linspace(1, 10, 100)
y_fit = slope * x_line + intercept
# 面向对象绘图
fig, ax = plt.subplots(figsize=(8, 4.5), dpi=100)
# 1. 绘制底层观测样本(散点)
ax.scatter(x_sample, y_sample, color='#C28B68', alpha=0.85,
edgecolors='#78350F', s=45, label='观测样本点')
# 2. 绘制上方拟合趋势曲线(折线)
ax.plot(x_line, y_fit, color='#6487A5', linewidth=2.4,
linestyle='-', label=f'拟合趋势线 (y={slope:.2f}x+{intercept:.2f})')
ax.set_title('采样点与线性拟合趋势叠加展示', fontsize=13, fontweight='bold', pad=12)
ax.set_xlabel('自变量 X', fontsize=11)
ax.set_ylabel('响应变量 Y', fontsize=11)
ax.grid(True, linestyle='--', alpha=0.45)
ax.legend(loc='upper left', framealpha=0.9)
plt.tight_layout()
plt.show()
五、图表选型总结与高频避坑指南
数据可视化的本质是降低理解成本。选择错误的图表类型或忽视渲染配置,往往会导致信息误读甚至脚本执行报错。以下梳理了从图表选型到生产导出的核心避坑决策模型:
1. 选型判定原则
| 图表类型 | 数据形态要求 | 核心分析目标 | 典型反模式(何时不应使用) |
|---|---|---|---|
| 折线图 (Line Plot) | X 轴具备固有次序(时间、连续距离、阶段) | 趋势走势、拐点定位、增减速率 | 无序的离散分类(如不同省份、不同水果);此时连线会造成虚假前后关联。 |
| 散点图 (Scatter Plot) | 两组或多组连续数值变量配对 | 相关性(正/负/不相关)、聚集区域、异常离群值 | 单变量分类统计;或者数据点超过 10 万个且未做下采样/热力图转换时,易导致渲染卡死。 |
| 双 Y 轴图 (twinx) | 共享同一 X 轴,但两个 Y 指标量纲单位悬殊 | 同屏对比绝对值规模与相对比率(如销售总额 vs 利润率) | 两条曲线单位一致却强行拆成两个 Y 轴,容易引起刻度视觉误导。 |
2. 常见问题排查与修复清单
- 问题 1:中文字符显示为白色小方块(ToFu 乱码)
原因:Matplotlib 默认回退到 DejaVu Sans 字体,该字体库不含中文字形。
解决:在脚本开头显式声明包含系统中可用的中文字体列表:
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']。 - 问题 2:坐标轴负数减号显示为空心方框
原因:引入中文字体后,部分字体将 Unicode 减号映射为了未定义字符。
解决:必须紧随其后声明:
plt.rcParams['axes.unicode_minus'] = False,指示 Matplotlib 使用标准 ASCII 连字符作为负号。 - 问题 3:导出图片边缘文字被切掉
原因:默认fig.savefig()采用固定外边距,当轴标签或图例较长时会超出绘制界限。
解决:在保存时添加bbox_inches='tight'参数,系统会自动重算图表紧凑包围盒:
fig.savefig('chart.png', dpi=300, bbox_inches='tight')。 - 问题 4:散点过于密集导致大片墨迹遮挡
原因:散点不透明时,上层点完全覆盖底层点,丧失了对样本密度高低的观察能力。
解决:调低透明度至alpha=0.3 ~ 0.6,配合缩小散点尺寸s=15,让高频区域通过颜色叠加自动变深。
通过遵循面向对象的代码规范、合理利用线型标记与四维视觉通道,并规范处理字体与边界参数,开发者便能高效产出清晰、严谨且具备发表级质感的数据图表。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













