摘要
在数据分析与机器学习领域,数据可视化是传递信息的关键环节。Matplotlib 作为 Python 生态中最经典的可视化库,凭借其灵活的定制能力和丰富的图表类型,成为开发者必备工具。本文将从环境搭建开始,逐步讲解 Matplotlib 的核心用法,最终通过实战案例带你掌握数据可视化的实用技巧。
一、环境搭建与基础配置
1.1 安装 Matplotlib
首先确保已安装 Python 环境(建议 3.7 及以上版本),通过 pip 命令快速安装:
# 基础安装
pip install matplotlib
# 若需支持中文显示,建议同时安装中文字体依赖
pip install matplotlib fonttools
1.2 基础配置(解决中文显示问题)
Matplotlib 默认不支持中文,需在代码开头添加配置:
import matplotlib.pyplot as plt
import numpy as np
# 配置中文显示
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei', 'SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示异常
二、Matplotlib 核心概念与基础图表
2.1 核心对象:Figure 与 Axes
Matplotlib 的绘图逻辑基于两大核心对象:
Figure:相当于画布,是所有图表的容器
Axes:相当于画布上的绘图区域,一个 Figure 可包含多个 Axes
创建基础绘图框架的两种方式:
# 方式1:plt.subplots()(推荐,支持多子图)
fig, ax = plt.subplots(figsize=(8, 5)) # figsize指定画布尺寸(宽, 高)
# 方式2:plt.figure() + add_subplot()
fig = plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111) # 1行1列第1个子图
2.2 常用基础图表实战
2.2.1 折线图(Line Plot)
适用于展示数据随时间或连续变量的变化趋势:
# 生成示例数据
x = np.linspace(0, 10, 100) # 0到10之间的100个均匀点
y1 = np.sin(x)
y2 = np.cos(x)
# 创建画布与子图
fig, ax = plt.subplots(figsize=(10, 6))
# 绘制折线图
ax.plot(x, y1, label='sin(x)', color='#FF6B6B', linewidth=2, linestyle='-')
ax.plot(x, y2, label='cos(x)', color='#4ECDC4', linewidth=2, linestyle='--')
# 添加图表元素
ax.set_title('正弦函数与余弦函数曲线', fontsize=14, pad=20) # 标题
ax.set_xlabel('x值', fontsize=12) # x轴标签
ax.set_ylabel('y值', fontsize=12) # y轴标签
ax.legend(fontsize=10) # 图例
ax.grid(True, alpha=0.3) # 网格线(alpha控制透明度)
# 保存图片(dpi控制分辨率,bbox_inches避免标签被截断)
plt.savefig('sin_cos_plot.png', dpi=300, bbox_inches='tight')
plt.show()
2.2.2 柱状图(Bar Plot)
适用于对比不同类别数据的数值大小:
# 示例数据:某产品季度销量
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
sales_2023 = [120, 180, 150, 210]
sales_2024 = [150, 200, 170, 240]
# 创建画布
fig, ax = plt.subplots(figsize=(10, 6))
# 设置柱状图位置(避免重叠)
x = np.arange(len(quarters))
width = 0.35
# 绘制双柱状图
bars1 = ax.bar(x - width/2, sales_2023, width, label='2023年', color='#95E1D3')
bars2 = ax.bar(x + width/2, sales_2024, width, label='2024年', color='#F38BA8')
# 在柱子顶部添加数值标签
def add_value_labels(bars):
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height + 5,
f'{int(height)}', ha='center', va='bottom', fontsize=10)
add_value_labels(bars1)
add_value_labels(bars2)
# 调整x轴标签
ax.set_xticks(x)
ax.set_xticklabels(quarters)
# 添加其他元素
ax.set_title('某产品2023-2024年季度销量对比', fontsize=14, pad=20)
ax.set_ylabel('销量(件)', fontsize=12)
ax.legend()
ax.grid(True, alpha=0.3, axis='y') # 仅显示y轴网格线
plt.savefig('sales_comparison.png', dpi=300, bbox_inches='tight')
plt.show()
三、进阶技巧:子图布局与样式定制
3.1 多子图布局(Subplot Layout)
通过plt.subplots()的nrows和ncols参数实现多子图排列:
# 创建2行2列的子图布局
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 10))
# 扁平化axes数组(便于循环操作)
axes = axes.flatten()
# 子图1:散点图
x = np.random.rand(100)
y = np.random.rand(100)
colors = np.random.rand(100)
axes[0].scatter(x, y, c=colors, cmap='viridis', alpha=0.6)
axes[0].set_title('散点图(颜色映射)')
# 子图2:直方图
data = np.random.normal(0, 1, 1000) # 正态分布数据
axes[1].hist(data, bins=30, color='#FFD93D', edgecolor='black')
axes[1].set_title('直方图(正态分布)')
# 子图3:饼图
labels = ['A', 'B', 'C', 'D']
sizes = [30, 25, 20, 25]
colors = ['#6BCF7F', '#4D96FF', '#FF7D00', '#FF5252']
axes[2].pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
axes[2].set_title('饼图(类别占比)')
# 子图4:箱线图
data = [np.random.normal(i, 1, 100) for i in range(4)]
axes[3].boxplot(data, labels=['组1', '组2', '组3', '组4'], patch_artist=True,
boxprops=dict(facecolor='#E8F4FD'))
axes[3].set_title('箱线图(数据分布)')
# 调整子图间距(避免标签重叠)
plt.tight_layout()
plt.savefig('multi_subplots.png', dpi=300, bbox_inches='tight')
plt.show()
3.2 样式定制(Style)
Matplotlib 提供多种预设样式,也支持自定义:
# 查看所有预设样式
print(plt.style.available)
# 使用预设样式
plt.style.use('seaborn-v0_8-talk') # 高对比度样式,适合演示
# 自定义样式(通过rcParams)
plt.rcParams.update({
'axes.backgroundcolor': '#F8F9FA',
'axes.titlecolor': '#2D3436',
'xtick.color': '#636E72',
'ytick.color': '#636E72',
'font.size': 11,
'legend.frameon': True,
'legend.framealpha': 0.9
})
四、实战案例:鸢尾花数据集可视化分析
结合 sklearn 的鸢尾花数据集,展示多维度可视化分析流程:
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X = iris.data # 特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度
y = iris.target # 标签:0=山鸢尾,1=变色鸢尾,2=维吉尼亚鸢尾
feature_names = iris.feature_names
target_names = iris.target_names
# 创建画布(2行2列子图,分析特征间相关性)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(14, 12))
axes = axes.flatten()
# 定义颜色与标记
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1']
markers = ['o', 's', '^']
# 子图1:花萼长度 vs 花萼宽度
for i in range(3):
mask = y == i
axes[0].scatter(X[mask, 0], X[mask, 1], c=colors[i], marker=markers[i],
label=target_names[i], s=60, alpha=0.7)
axes[0].set_xlabel(feature_names[0])
axes[0].set_ylabel(feature_names[1])
axes[0].set_title('花萼长度 vs 花萼宽度')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 子图2:花瓣长度 vs 花瓣宽度
for i in range(3):
mask = y == i
axes[1].scatter(X[mask, 2], X[mask, 3], c=colors[i], marker=markers[i],
label=target_names[i], s=60, alpha=0.7)
axes[1].set_xlabel(feature_names[2])
axes[1].set_ylabel(feature_names[3])
axes[1].set_title('花瓣长度 vs 花瓣宽度')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
# 子图3:特征分布箱线图
X_T = X.T # 转置后按特征分组
bp = axes[2].boxplot(X_T, labels=[name.replace(' (cm)', '') for name in feature_names],
patch_artist=True)
for patch, color in zip(bp['boxes'], ['#FFEAA7', '#81ECEC', '#FD79A8', '#FDCB6E']):
patch.set_facecolor(color)
axes[2].set_title('各特征分布箱线图')
axes[2].set_ylabel('特征值(cm)')
# 子图4:特征相关性热力图
corr = np.corrcoef(X.T)
im = axes[3].imshow(corr, cmap='RdYlBu_r', vmin=-1, vmax=1)
# 添加数值标签
for i in range(len(feature_names)):
for j in range(len(feature_names)):
axes[3].text(j, i, f'{corr[i, j]:.2f}', ha='center', va='center',
color='white' if abs(corr[i, j]) > 0.5 else 'black')
# 设置坐标轴标签
short_names = [name.split(' ')[0] + '
' + name.split(' ')[1] for name in feature_names]
axes[3].set_xticks(range(len(feature_names)))
axes[3].set_yticks(range(len(feature_names)))
axes[3].set_xticklabels(short_names)
axes[3].set_yticklabels(short_names)
axes[3].set_title('特征相关性热力图')
# 添加颜色条
cbar = plt.colorbar(im, ax=axes[3], shrink=0.8)
cbar.set_label('相关系数', rotation=270, labelpad=15)
plt.tight_layout()
plt.savefig('iris_visualization.png', dpi=300, bbox_inches='tight')
plt.show()
五、常见问题与解决方案
中文显示乱码:参考 1.2 节配置中文字体,若仍有问题,检查字体是否安装(如 Windows 的 “SimHei”、Linux 的 “WenQuanYi Zen Hei”)。
图片保存后标签被截断:plt.savefig()中添加bbox_inches='tight'参数。
子图间距过小:使用plt.tight_layout()或fig.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)手动调整。
图表样式不统一:通过plt.rcParams或plt.style.use()预设全局样式。
总结
Matplotlib 的核心优势在于高度可定制性,从基础的折线图、柱状图到复杂的多子图布局,都能满足不同场景的可视化需求。本文通过 “基础配置→核心图表→进阶技巧→实战案例” 的流程,带你快速上手 Matplotlib。建议在实际项目中结合具体数据场景,灵活调整图表类型与样式,让数据可视化真正成为数据分析的 “利器”。
如果本文对你有帮助,欢迎点赞、收藏,也欢迎在评论区分享你的 Matplotlib 使用技巧或问题!
暂无评论内容