Matplotlib 散点图(Scatter)完全指南
散点图是 数据分析、科学可视化、机器学习结果展示 的核心工具。本教程带你从入门到 发表级,掌握 基础绘制、颜色/大小/形状映射、气泡图、3D散点、动画、交互式标注、聚类可视化 等全部技巧。
一、基本散点图
import matplotlib.pyplot as plt
import numpy as np
# 生成数据
x = np.random.randn(100)
y = np.random.randn(100)
plt.scatter(x, y)
plt.show()
二、核心参数详解
plt.scatter(x, y,
s=50, # 点大小
c='blue', # 颜色
marker='o', # 标记形状
alpha=0.7, # 透明度
edgecolors='k', # 边框颜色
linewidths=1) # 边框宽度
三、颜色映射(Color Mapping)—— 第四维数据
z = np.random.rand(100) # 第三维数据
plt.scatter(x, y, c=z, cmap='viridis', s=60)
plt.colorbar(label='Z 值') # 显示颜色条
plt.show()
常用 cmap 配色方案
| 名称 | 用途 |
|---|---|
'viridis' | 默认推荐,色盲友好 |
'plasma' | 高对比 |
'inferno' | 深色背景 |
'cividis' | 色盲优化 |
'coolwarm' | 发散数据 |
'Set1' | 分类数据 |
plt.scatter(x, y, c=z, cmap='plasma', s=80, edgecolors='white', linewidth=0.5)
四、大小映射(Size Mapping)—— 第五维数据(气泡图)
size = np.random.rand(100) * 1000 # 大小范围 0~1000
plt.scatter(x, y, s=size, alpha=0.6, c='red')
plt.title('气泡图:点越大,值越大')
plt.show()
综合:颜色 + 大小映射
plt.scatter(x, y,
s=size,
c=z,
cmap='viridis',
alpha=0.7,
edgecolors='k',
linewidth=0.5)
plt.colorbar(label='强度')
plt.title('气泡图:颜色=强度,大小=体积')
plt.show()
五、标记样式(Marker)
| 标记 | 代码 | 说明 |
|---|---|---|
| 圆 | 'o' | 默认 |
| 方 | 's' | 方形 |
| 三角 | '^', 'v', '<', '>' | 方向 |
| 星 | '*' | 醒目 |
| 十字 | '+', 'x' | 精确定位 |
| 菱形 | 'D' | 分类 |
markers = ['o', 's', '^', 'D', '*']
colors = ['red', 'blue', 'green', 'purple', 'orange']
for i, (m, c) in enumerate(zip(markers, colors)):
plt.scatter(x[i*20:(i+1)*20], y[i*20:(i+1)*20],
marker=m, c=c, s=80, label=f'组 {i+1}')
plt.legend()
plt.show()
六、面向对象方式(推荐)
fig, ax = plt.subplots(figsize=(10, 8))
sc = ax.scatter(x, y,
c=z, s=size,
cmap='plasma',
alpha=0.8,
edgecolors='white',
linewidth=0.5)
ax.set_xlabel('X 轴', fontsize=12)
ax.set_ylabel('Y 轴', fontsize=12)
ax.set_title('专业散点图', fontsize=16, fontweight='bold')
plt.colorbar(sc, label='强度', shrink=0.8)
plt.grid(True, alpha=0.3)
plt.show()
七、3D 散点图
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z,
c=z, cmap='viridis',
s=60, depthshade=True)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.title('3D 散点图')
plt.show()
八、标注数据点(Annotation)
# 标注前3个最大点
idx = np.argsort(z)[-3:] # 最大3个
for i in idx:
plt.annotate(f'({x[i]:.2f}, {y[i]:.2f})',
(x[i], y[i]),
xytext=(5, 5), textcoords='offset points',
fontsize=9, color='red',
arrowprops=dict(arrowstyle='->', color='red'))
plt.scatter(x, y, c=z, cmap='viridis')
plt.colorbar()
plt.show()
九、聚类可视化(KMeans 示例)
from sklearn.cluster import KMeans
# 模拟聚类数据
X = np.random.randn(300, 2)
X[:100] += 3
X[100:200] += [3, -3]
X[200:] += [-3, -2]
# 聚类
kmeans = KMeans(n_clusters=3).fit(X)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
# 绘图
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='Set1', s=50, alpha=0.8)
plt.scatter(centers[:, 0], centers[:, 1],
c='black', marker='x', s=200, linewidth=3, label='中心')
for i, center in enumerate(centers):
plt.annotate(f'中心 {i}', center, xytext=(5,5),
textcoords='offset points', fontweight='bold')
plt.legend()
plt.title('KMeans 聚类散点图')
plt.show()
十、完整专业示例(论文级)
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('seaborn-v0_8')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 生成模拟数据
np.random.seed(42)
n = 200
x = np.random.randn(n)
y = 1.5 * x + np.random.randn(n) * 0.8
size = np.random.rand(n) * 800 + 100
intensity = np.sqrt(x**2 + y**2)
group = (x > 0).astype(int) + (y > 0).astype(int) * 2 # 4个象限分组
# 创建画布
fig, ax = plt.subplots(figsize=(12, 9))
# 散点图:颜色=强度,大小=体积,形状=象限
markers = ['o', 's', '^', 'D']
colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']
for g in range(4):
mask = group == g
sc = ax.scatter(x[mask], y[mask],
s=size[mask],
c=[intensity[mask]], cmap='plasma',
marker=markers[g],
edgecolors='white', linewidth=0.8,
alpha=0.85,
label=f'第{g+1}象限')
# 颜色条
cbar = plt.colorbar(sc, shrink=0.8, pad=0.02)
cbar.set_label('强度 (√(x²+y²))', fontsize=12)
# 拟合线
m, b = np.polyfit(x, y, 1)
ax.plot(x, m*x + b, 'k--', linewidth=2, label=f'拟合线: y={m:.2f}x+{b:.2f}')
# 美化
ax.set_title('多维散点图专业展示', fontsize=18, fontweight='bold', pad=20)
ax.set_xlabel('特征 X', fontsize=14)
ax.set_ylabel('特征 Y', fontsize=14)
ax.legend(loc='upper left', frameon=True, fancybox=True, shadow=True)
# 网格
ax.grid(True, alpha=0.3, linestyle='--')
ax.set_facecolor('#f8f9fa')
# 标注极端点
max_idx = np.argmax(intensity)
ax.annotate(f'最强点\n({x[max_idx]:.2f}, {y[max_idx]:.2f})',
(x[max_idx], y[max_idx]),
xytext=(20, -20), textcoords='offset points',
fontsize=10, color='red', fontweight='bold',
arrowprops=dict(arrowstyle='->', color='red', lw=1.5),
bbox=dict(boxstyle="round,pad=0.3", facecolor='yellow', alpha=0.7))
plt.tight_layout()
plt.savefig('scatter_pro.png', dpi=300, bbox_inches='tight', facecolor='white')
plt.show()
十一、散点图速查表(收藏用)
# 基础
plt.scatter(x, y)
# 颜色映射
plt.scatter(x, y, c=z, cmap='viridis')
plt.colorbar()
# 大小映射
plt.scatter(x, y, s=size)
# 综合
plt.scatter(x, y, s=size, c=z, cmap='plasma', alpha=0.7)
# 3D
ax.scatter(x, y, z, c=z, cmap='viridis')
# 标注
plt.annotate('文本', (x0,y0), xytext=(dx,dy), textcoords='offset points')
# 拟合线
m, b = np.polyfit(x, y, 1)
plt.plot(x, m*x + b, 'r--')
十二、常见问题解决
| 问题 | 解决方案 |
|---|---|
| 点重叠看不清 | alpha=0.5~0.7 + edgecolors='white' |
| 颜色条太长 | plt.colorbar(..., shrink=0.8) |
| 点太大挡住 | s=size*0.1 缩放 |
| 3D 看不清 | 旋转视角 ax.view_init(30, 45) |
| 保存裁剪 | plt.savefig(..., bbox_inches='tight') |
十三、推荐配色 + 标记组合
| 用途 | 推荐 |
|---|---|
| 论文 | cmap='viridis', marker='o', edgecolors='k' |
| PPT | cmap='plasma', s=100, alpha=0.8 |
| 分类 | cmap='Set1', 不同 marker |
| 气泡图 | c='gray', s=size, alpha=0.6 |
官方文档
- 散点图 API:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html
- 3D 散点:https://matplotlib.org/stable/gallery/mplot3d/scatter3d.html
- 示例图库:https://matplotlib.org/stable/gallery/shapes_and_collections/scatter.html
总结:三步打造专业散点图
# 1. 数据准备(x, y, c, s)
# 2. 绘制
sc = ax.scatter(x, y, c=c, s=s, cmap='viridis', edgecolors='white')
# 3. 美化
plt.colorbar(sc, label='强度')
ax.grid(True, alpha=0.3)
ax.set_title('标题', fontsize=16)
一键生成气泡图:
plt.scatter(x, y, s=np.random.rand(100)*1000, c=np.random.rand(100),
cmap='coolwarm', alpha=0.7, edgecolors='k')
plt.colorbar()
plt.show()
需要我为你:
- 生成 10种经典散点图模板?
- 制作 Jupyter 散点图交互小工具(滑块控制大小/颜色)?
- 输出 LaTeX/PPT 可用代码?
告诉我你的需求!