文章目录
- 前言
- 一、简介与安装
- [二、 基础绘图框架](#二、 基础绘图框架)
- [三、 折线图(Line Plot)](#三、 折线图(Line Plot))
-
- [3.1 基本折线图](#3.1 基本折线图)
- [3.2 多线对比折线图](#3.2 多线对比折线图)
- [3.3 子图布局](#3.3 子图布局)
- [四、 散点图(Scatter Plot)](#四、 散点图(Scatter Plot))
- [五、 直方图(Histogram)](#五、 直方图(Histogram))
- [六、 柱状图(Bar Chart)](#六、 柱状图(Bar Chart))
-
- [6.1 分组柱状图](#6.1 分组柱状图)
- [6.2 堆叠柱状图](#6.2 堆叠柱状图)
- [七、饼图(Pie Chart)](#七、饼图(Pie Chart))
- [八、 专业技巧与最佳实践](#八、 专业技巧与最佳实践)
-
- [8.1 解决中文显示问题](#8.1 解决中文显示问题)
- [8.2 图表样式定制](#8.2 图表样式定制)
- [8.3 保存高质量图表](#8.3 保存高质量图表)
- [8.4 交互式功能](#8.4 交互式功能)
- [九、 实用工具函数](#九、 实用工具函数)
- [十、 学习资源推荐](#十、 学习资源推荐)
- 总结
前言
本文介绍了Python数据可视化库Matplotlib的基础使用方法。主要内容包括:1) Matplotlib的安装方法及核心特性,支持专业级可视化与高度定制;2) 基础绘图框架,展示如何创建图表、设置属性和添加网格线;3) 折线图的绘制方法,包括单线图、多线对比图和子图布局;4) 散点图的应用,通过示例展示如何可视化变量关系并计算相关系数。文章提供了丰富的代码示例,涵盖图表装饰、多子图布局等实用技巧,适合数据分析人员快速掌握Matplotlib的核心功能。
一、简介与安装
Matplotlib 是 Python 生态系统中功能最全面的绘图库之一,它提供了丰富的绘图工具,能够创建高质量的折线图、散点图、柱状图、饼图等多种统计图表。该库通常与 NumPy 协同工作,构成科学计算和数据分析的核心工具链。
主要特性:
专业级可视化:支持出版物级别的图表输出
高度可定制:从图表样式到元素细节均可精细调整
多平台支持:可在 Jupyter Notebook、独立脚本和 Web 应用中使用
广泛兼容:与 Pandas、Seaborn 等数据分析库无缝集成
安装方法:
python
bash
# 基础安装
pip install matplotlib
# 通过科学计算发行版安装(推荐)
conda install matplotlib # 适用于 Anaconda/Miniconda 用户
二、 基础绘图框架
Matplotlib 采用分层设计,主要包含以下组件:
python
python
import matplotlib.pyplot as plt
import numpy as np
# 创建图表和坐标轴
fig, ax = plt.subplots(figsize=(10, 6))
# 设置图表属性
ax.set_title('图表标题', fontsize=16, pad=20)
ax.set_xlabel('X轴标签', fontsize=12)
ax.set_ylabel('Y轴标签', fontsize=12)
# 添加网格线
ax.grid(True, alpha=0.3, linestyle='--')
# 显示图表
plt.tight_layout()
plt.show()
三、 折线图(Line Plot)
折线图适用于展示数据随时间或其他连续变量的变化趋势。
3.1 基本折线图
python
python
# 单线折线图示例
x = np.arange(1, 13) # 1月至12月
y = [23, 25, 22, 28, 30, 32, 35, 33, 29, 26, 24, 22] # 月平均温度
plt.figure(figsize=(12, 6))
# 创建折线图
plt.plot(x, y,
marker='o', # 数据点标记
markersize=8, # 标记大小
linewidth=2, # 线宽
color='#3498db', # 颜色(十六进制)
linestyle='-', # 线型
label='2023年温度')
# 图表装饰
plt.title('月平均温度变化趋势', fontsize=16, fontweight='bold')
plt.xlabel('月份', fontsize=12)
plt.ylabel('温度 (°C)', fontsize=12)
# 设置刻度
plt.xticks(x, ['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月'])
plt.yticks(range(20, 38, 2))
# 添加图例
plt.legend(loc='upper left', fontsize=11)
# 添加数据标签
for xi, yi in zip(x, y):
plt.text(xi, yi + 0.5, f'{yi}°', ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.show()
3.2 多线对比折线图
python
python
# 多线对比示例:历年温度对比
years = np.arange(2020, 2024)
months = np.arange(1, 13)
# 生成示例数据
np.random.seed(42)
temperatures = {
2020: np.random.normal(25, 5, 12),
2021: np.random.normal(26, 4, 12),
2022: np.random.normal(27, 3, 12),
2023: np.random.normal(26.5, 3.5, 12)
}
plt.figure(figsize=(14, 8))
# 定义颜色和线型
colors = ['#e74c3c', '#3498db', '#2ecc71', '#9b59b6']
linestyles = ['-', '--', '-.', ':']
# 绘制多条折线
for i, (year, temps) in enumerate(temperatures.items()):
plt.plot(months, temps,
marker='o',
markersize=6,
linewidth=2,
color=colors[i],
linestyle=linestyles[i],
label=f'{year}年',
alpha=0.8)
# 图表设置
plt.title('历年月平均温度对比', fontsize=18, fontweight='bold', pad=20)
plt.xlabel('月份', fontsize=14)
plt.ylabel('平均温度 (°C)', fontsize=14)
# 月份标签
month_labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
plt.xticks(months, month_labels, rotation=45)
# 添加网格和图例
plt.grid(True, alpha=0.2, linestyle='--')
plt.legend(loc='upper left', fontsize=12, framealpha=0.9)
plt.tight_layout()
plt.show()
3.3 子图布局
python
python
# 多子图示例
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
fig.suptitle('数据可视化子图示例', fontsize=20, fontweight='bold', y=1.02)
# 生成数据
x = np.linspace(0, 10, 100)
# 子图1:线性关系
axes[0, 0].plot(x, 2*x + 3, 'b-', linewidth=2)
axes[0, 0].set_title('线性函数', fontsize=14)
axes[0, 0].set_xlabel('x')
axes[0, 0].set_ylabel('y = 2x + 3')
axes[0, 0].grid(True, alpha=0.3)
# 子图2:正弦函数
axes[0, 1].plot(x, np.sin(x), 'r--', linewidth=2)
axes[0, 1].set_title('正弦函数', fontsize=14)
axes[0, 1].set_xlabel('x')
axes[0, 1].set_ylabel('sin(x)')
axes[0, 1].grid(True, alpha=0.3)
# 子图3:指数函数
axes[1, 0].plot(x, np.exp(x/3), 'g-.', linewidth=2)
axes[1, 0].set_title('指数函数', fontsize=14)
axes[1, 0].set_xlabel('x')
axes[1, 0].set_ylabel('exp(x/3)')
axes[1, 0].set_yscale('log')
axes[1, 0].grid(True, alpha=0.3)
# 子图4:二次函数
axes[1, 1].plot(x, x**2 - 5*x + 6, 'm:', linewidth=2)
axes[1, 1].set_title('二次函数', fontsize=14)
axes[1, 1].set_xlabel('x')
axes[1, 1].set_ylabel('x² - 5x + 6')
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
四、 散点图(Scatter Plot)
散点图用于展示两个变量之间的关系,常用于发现数据中的模式、异常值或相关性。
python
python
# 散点图高级示例
np.random.seed(42)
# 生成模拟数据
n_points = 200
x1 = np.random.normal(50, 15, n_points)
y1 = 2 * x1 + np.random.normal(0, 20, n_points) + 30
x2 = np.random.normal(80, 12, n_points)
y2 = -1.5 * x2 + np.random.normal(0, 15, n_points) + 200
# 计算相关系数
corr1 = np.corrcoef(x1, y1)[0, 1]
corr2 = np.corrcoef(x2, y2)[0, 1]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# 第一个散点图
scatter1 = ax1.scatter(x1, y1,
c=y1, # 颜色映射
cmap='viridis', # 色谱
s=80, # 点大小
alpha=0.7, # 透明度
edgecolors='w', # 边缘颜色
linewidth=0.5)
ax1.set_title(f'正相关数据集 (r = {corr1:.2f})', fontsize=14)
ax1.set_xlabel('变量 X', fontsize=12)
ax1.set_ylabel('变量 Y', fontsize=12)
# 添加颜色条
cbar1 = plt.colorbar(scatter1, ax=ax1)
cbar1.set_label('Y 值大小', fontsize=10)
# 第二个散点图
scatter2 = ax2.scatter(x2, y2,
c=x2, # 根据 x 值着色
cmap='plasma',
s=80,
alpha=0.7,
edgecolors='w',
linewidth=0.5)
ax2.set_title(f'负相关数据集 (r = {corr2:.2f})', fontsize=14)
ax2.set_xlabel('变量 X', fontsize=12)
ax2.set_ylabel('变量 Y', fontsize=12)
# 添加颜色条
cbar2 = plt.colorbar(scatter2, ax=ax2)
cbar2.set_label('X 值大小', fontsize=10)
# 添加趋势线
for ax, x_data, y_data in [(ax1, x1, y1), (ax2, x2, y2)]:
z = np.polyfit(x_data, y_data, 1)
p = np.poly1d(z)
ax.plot(x_data, p(x_data), "r--", alpha=0.8, linewidth=2)
plt.tight_layout()
plt.show()
五、 直方图(Histogram)
直方图用于展示数据的分布情况,特别适合分析连续变量的频率分布。
python
python
# 直方图高级示例
np.random.seed(42)
# 生成多组数据
data1 = np.random.normal(75, 10, 5000) # 正态分布
data2 = np.random.exponential(20, 3000) + 50 # 指数分布
data3 = np.random.uniform(40, 100, 4000) # 均匀分布
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10))
# 子图1:叠加直方图
ax1.hist([data1, data2, data3],
bins=50,
color=['#3498db', '#e74c3c', '#2ecc71'],
alpha=0.7,
edgecolor='black',
linewidth=0.5,
label=['正态分布', '指数分布', '均匀分布'],
density=True) # 归一化为概率密度
ax1.set_title('不同分布数据对比', fontsize=16, fontweight='bold')
ax1.set_xlabel('数值', fontsize=12)
ax1.set_ylabel('概率密度', fontsize=12)
ax1.legend(fontsize=11)
ax1.grid(True, alpha=0.2)
# 添加统计信息
stats_text = f'''数据统计:
正态分布: μ={data1.mean():.1f}, σ={data1.std():.1f}
指数分布: λ={1/(data2.mean()-50):.3f}
均匀分布: [{data3.min():.1f}, {data3.max():.1f}]'''
ax1.text(0.02, 0.98, stats_text,
transform=ax1.transAxes,
fontsize=10,
verticalalignment='top',
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
# 子图2:累计分布直方图
counts1, bins1, patches1 = ax2.hist(data1,
bins=50,
color='skyblue',
alpha=0.7,
edgecolor='black',
linewidth=0.5,
cumulative=True,
density=True,
label='累计分布')
ax2.set_title('累计分布函数 (CDF)', fontsize=16, fontweight='bold')
ax2.set_xlabel('数值', fontsize=12)
ax2.set_ylabel('累计概率', fontsize=12)
ax2.grid(True, alpha=0.2)
# 添加分位数线
percentiles = [25, 50, 75, 95]
colors = ['red', 'orange', 'green', 'purple']
for p, color in zip(percentiles, colors):
value = np.percentile(data1, p)
ax2.axvline(x=value, color=color, linestyle='--', alpha=0.7, linewidth=1.5)
ax2.text(value, 0.9, f'{p}%: {value:.1f}',
rotation=90, fontsize=9, color=color,
ha='right', va='top')
ax2.legend(fontsize=11)
plt.tight_layout()
plt.show()
六、 柱状图(Bar Chart)
柱状图用于比较不同类别之间的数值差异,特别适合展示离散数据。
6.1 分组柱状图
python
python
# 分组柱状图示例:学生成绩对比
students = ['张三', '李四', '王五', '赵六', '孙七']
subjects = ['语文', '数学', '英语', '物理', '化学']
# 生成模拟成绩数据
np.random.seed(42)
scores = np.random.randint(60, 101, size=(len(students), len(subjects)))
fig, ax = plt.subplots(figsize=(14, 8))
# 设置柱状图参数
bar_width = 0.15
x_pos = np.arange(len(students))
# 不同颜色表示不同科目
colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6']
# 绘制分组柱状图
for i, (subject, color) in enumerate(zip(subjects, colors)):
ax.bar(x_pos + i * bar_width,
scores[:, i],
width=bar_width,
color=color,
alpha=0.8,
edgecolor='black',
linewidth=0.5,
label=subject)
# 图表设置
ax.set_title('学生各科成绩对比', fontsize=18, fontweight='bold', pad=20)
ax.set_xlabel('学生姓名', fontsize=14)
ax.set_ylabel('成绩', fontsize=14)
ax.set_xticks(x_pos + bar_width * (len(subjects) - 1) / 2)
ax.set_xticklabels(students, fontsize=12)
ax.set_ylim([50, 105])
# 添加网格和背景色
ax.grid(True, alpha=0.2, axis='y')
ax.set_axisbelow(True) # 网格线在柱子下方
# 添加数据标签
for i in range(len(students)):
for j in range(len(subjects)):
height = scores[i, j]
ax.text(x_pos[i] + j * bar_width,
height + 0.5,
str(height),
ha='center',
va='bottom',
fontsize=10,
fontweight='bold')
# 添加图例
ax.legend(title='科目', fontsize=11, title_fontsize=12, loc='upper left')
# 添加总分信息
total_scores = scores.sum(axis=1)
for i, total in enumerate(total_scores):
ax.text(x_pos[i] + bar_width * (len(subjects) - 1) / 2,
-5,
f'总分: {total}',
ha='center',
va='top',
fontsize=11,
fontweight='bold',
color='darkred')
plt.tight_layout()
plt.show()
6.2 堆叠柱状图
python
python
# 堆叠柱状图示例:销售额构成
months = ['1月', '2月', '3月', '4月', '5月', '6月']
products = ['产品A', '产品B', '产品C', '产品D']
# 生成销售数据
np.random.seed(42)
sales_data = np.random.randint(20, 100, size=(len(months), len(products)))
fig, ax = plt.subplots(figsize=(14, 8))
# 定义颜色
colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12']
# 绘制堆叠柱状图
bottom_values = np.zeros(len(months))
for i, (product, color) in enumerate(zip(products, colors)):
ax.bar(months, sales_data[:, i],
bottom=bottom_values,
color=color,
alpha=0.8,
edgecolor='black',
linewidth=0.5,
label=product)
bottom_values += sales_data[:, i]
# 图表设置
ax.set_title('各月销售额构成(堆叠柱状图)', fontsize=18, fontweight='bold', pad=20)
ax.set_xlabel('月份', fontsize=14)
ax.set_ylabel('销售额(万元)', fontsize=14)
ax.set_ylim([0, 320])
# 添加总数标签
for i, month in enumerate(months):
total = sales_data[i].sum()
ax.text(i, total + 5,
f'合计: {total}',
ha='center',
va='bottom',
fontsize=11,
fontweight='bold')
# 添加百分比标签(可选)
for i, month in enumerate(months):
current_bottom = 0
for j in range(len(products)):
value = sales_data[i, j]
percentage = value / sales_data[i].sum() * 100
if percentage > 10: # 只显示较大的部分
ax.text(i, current_bottom + value/2,
f'{percentage:.0f}%',
ha='center',
va='center',
fontsize=9,
fontweight='bold',
color='white')
current_bottom += value
ax.legend(title='产品类别', fontsize=11, title_fontsize=12)
ax.grid(True, alpha=0.2, axis='y')
ax.set_axisbelow(True)
plt.tight_layout()
plt.show()
七、饼图(Pie Chart)
饼图用于展示各部分占整体的比例关系,适合表现百分比数据。
python
python
# 饼图高级示例:市场份额分析
companies = ['Apple', 'Samsung', '华为', '小米', 'OPPO', 'Vivo', '其他']
market_share = [25.3, 19.2, 15.8, 12.5, 8.7, 7.9, 10.6]
# 颜色方案
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4',
'#FFEAA7', '#DDA0DD', '#B2B2B2']
# 突出显示前两名
explode = [0.1 if i < 2 else 0 for i in range(len(companies))]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
# 子图1:基础饼图
wedges1, texts1, autotexts1 = ax1.pie(market_share,
explode=explode,
labels=companies,
colors=colors,
autopct='%1.1f%%',
startangle=90,
shadow=True,
textprops={'fontsize': 11})
# 美化百分比标签
for autotext in autotexts1:
autotext.set_color('white')
autotext.set_fontweight('bold')
ax1.set_title('全球智能手机市场份额', fontsize=16, fontweight='bold', pad=20)
# 子图2:环形图
wedges2, texts2, autotexts2 = ax2.pie(market_share,
explode=explode,
labels=companies,
colors=colors,
autopct='%1.1f%%',
startangle=90,
wedgeprops={'width': 0.4, 'edgecolor': 'w'})
# 转换为环形图
centre_circle = plt.Circle((0, 0), 0.25, color='white', linewidth=0)
ax2.add_artist(centre_circle)
# 添加中央文本
ax2.text(0, 0, '2023年\n市场分析',
horizontalalignment='center',
verticalalignment='center',
fontsize=14,
fontweight='bold')
ax2.set_title('市场份额环形图', fontsize=16, fontweight='bold', pad=20)
# 添加图例
fig.legend(wedges1, companies,
title="品牌",
loc="center right",
fontsize=11,
title_fontsize=12,
bbox_to_anchor=(1.15, 0.5))
plt.tight_layout()
plt.show()
八、 专业技巧与最佳实践
8.1 解决中文显示问题
python
python
# 方法1:使用系统字体
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 方法2:指定字体文件
import matplotlib
matplotlib.font_manager.fontManager.addfont('path/to/your/font.ttf')
font_name = matplotlib.font_manager.FontProperties(fname='path/to/your/font.ttf').get_name()
plt.rcParams['font.sans-serif'] = [font_name]
8.2 图表样式定制
python
python
# 使用预定义样式
plt.style.use('seaborn-v0_8-darkgrid') # 内置样式
# 自定义样式
plt.rcParams.update({
'figure.figsize': (10, 6),
'axes.titlesize': 16,
'axes.labelsize': 12,
'xtick.labelsize': 10,
'ytick.labelsize': 10,
'legend.fontsize': 11,
'grid.alpha': 0.3,
'lines.linewidth': 2,
'lines.markersize': 8,
})
8.3 保存高质量图表
python
python
# 保存图表
fig.savefig('chart.png',
dpi=300, # 分辨率
bbox_inches='tight', # 紧凑布局
facecolor='white', # 背景色
edgecolor='none', # 边框颜色
transparent=False) # 透明度
8.4 交互式功能
python
python
# 启用交互模式
plt.ion() # 交互模式
# 创建可交互图表
fig, ax = plt.subplots()
line, = ax.plot([], [])
# 动态更新数据
def update_data(new_data):
line.set_data(range(len(new_data)), new_data)
ax.relim()
ax.autoscale_view()
fig.canvas.draw_idle()
# 关闭交互模式
plt.ioff()
九、 实用工具函数
python
python
def create_dashboard(data_dict, figsize=(16, 12)):
"""创建综合数据仪表板"""
fig = plt.figure(figsize=figsize)
fig.suptitle('数据分析仪表板', fontsize=20, fontweight='bold')
# 创建子图网格
gs = fig.add_gridspec(3, 3)
# 添加不同类型的图表
ax1 = fig.add_subplot(gs[0, :2]) # 折线图
ax2 = fig.add_subplot(gs[0, 2]) # 饼图
ax3 = fig.add_subplot(gs[1, :]) # 柱状图
ax4 = fig.add_subplot(gs[2, :]) # 散点图
# 这里添加具体的绘图代码
# ...
plt.tight_layout()
return fig
def annotate_chart(ax, annotations):
"""为图表添加批注"""
for annotation in annotations:
ax.annotate(annotation['text'],
xy=annotation['xy'],
xytext=annotation['xytext'],
arrowprops=dict(arrowstyle='->', color='gray'),
fontsize=10,
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
十、 学习资源推荐
官方文档:https://matplotlib.org/stable/contents.html
图库示例:https://matplotlib.org/stable/gallery/index.html
交互式教程:Jupyter Notebook + Matplotlib 练习
进阶学习:
Seaborn:基于 Matplotlib 的高级统计绘图
Plotly:交互式可视化
Bokeh:Web 交互式可视化
总结
Matplotlib 是一个功能强大且灵活的可视化工具,通过掌握上述技巧,您将能够创建专业级别的数据可视化图表,有效传达数据分析结果。建议从基础图表开始,逐步探索高级功能,最终形成自己的可视化风格和工作流程。