📊 章节概览
散点图是最基础也最重要的数据可视化方法之一。本章系统学习三大Python可视化库的散点图绘制方法, 并通过鸢尾花数据集、正态分布、蒙特卡洛方法等实际案例,掌握散点图的应用技巧。
📐 Matplotlib
基础散点图、网格与随机分布
🌺 Seaborn
高级API、自动配色与分组
📈 Plotly
交互式气泡图与动态探索
7.1 Matplotlib散点图:规则网格 vs 随机散点
使用pyplot.scatter()绘制不同分布的散点
10400
Python代码(Matplotlib):
import matplotlib.pyplot as plt
import numpy as np
# 规则网格数据
x = np.linspace(0, 10, int(np.sqrt(100)))
y = np.linspace(0, 10, int(np.sqrt(100)))
X, Y = np.meshgrid(x, y)
plt.scatter(X.flatten(), Y.flatten(), c='blue', alpha=0.7)
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.title('规则网格散点图')
plt.show()💡 关键特性:
• 规则网格:使用np.meshgrid()创建均匀分布的点
• 随机散点:使用np.random.rand()生成随机分布
• pyplot.scatter():基础散点图绘制方法,支持颜色、大小、透明度等参数
• 规则网格:使用np.meshgrid()创建均匀分布的点
• 随机散点:使用np.random.rand()生成随机分布
• pyplot.scatter():基础散点图绘制方法,支持颜色、大小、透明度等参数
7.2 Seaborn鸢尾花散点图:多维数据可视化
使用seaborn.scatterplot()展示鸢尾花数据集
Python代码(Seaborn):
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
# 加载鸢尾花数据
iris = load_iris(as_frame=True)
df = iris.frame
# 绘制散点图
sns.scatterplot(data=df,
x='sepal_length',
y='sepal_width',
hue='target',
palette='Set1',
alpha=0.7)
plt.xlabel('花萼长度')
plt.ylabel('花萼宽度')
plt.title('鸢尾花散点图')
plt.show()💡 Seaborn优势:
• 自动为不同类别分配颜色(hue参数)
• 内置多种美观的配色方案(palette)
• 更高级的API,代码更简洁
• 自动生成图例
• 自动为不同类别分配颜色(hue参数)
• 内置多种美观的配色方案(palette)
• 更高级的API,代码更简洁
• 自动生成图例
7.3 散点包络线:ConvexHull凸包可视化
计算并显示散点集合的凸包边界
550
总点数
20
凸包顶点数
8
内部点数
12
Python代码(使用scipy):
from scipy.spatial import ConvexHull
import numpy as np
import matplotlib.pyplot as plt
# 生成随机点
points = np.random.rand(20, 2) * 8 + 1
# 计算凸包
hull = ConvexHull(points)
# 绘制散点和凸包
plt.scatter(points[:, 0], points[:, 1], c='blue', alpha=0.6)
for simplex in hull.simplices:
plt.plot(points[simplex, 0], points[simplex, 1], 'g-', lw=2)
plt.scatter(points[hull.vertices, 0], points[hull.vertices, 1],
c='red', s=100, marker='o')
plt.title('Convex Hull')
plt.show()💡 凸包(Convex Hull):
• 包含所有点的最小凸多边形
• 红色点是凸包的顶点(在边界上)
• 蓝色点是内部点(被凸包包围)
• 使用Graham扫描算法计算,时间复杂度O(n log n)
• 包含所有点的最小凸多边形
• 红色点是凸包的顶点(在边界上)
• 蓝色点是内部点(被凸包包围)
• 使用Graham扫描算法计算,时间复杂度O(n log n)
7.5 Plotly气泡图:Gapminder数据可视化
探索全球健康、财富与人口的关系演变
19602020
Python代码(Plotly):
import plotly.express as px
# 加载Gapminder数据
df = px.data.gapminder()
df_year = df[df['year'] == 2000]
# 创建气泡图
fig = px.scatter(df_year,
x="gdpPercap",
y="lifeExp",
size="pop", # 气泡大小 = 人口
color="continent", # 颜色 = 洲际
hover_name="country",
log_x=True, # X轴对数刻度
size_max=60,
title=f'Gapminder 2000')
fig.show()💡 气泡图的三个维度:
• X轴:人均GDP(财富水平,对数刻度)
• Y轴:预期寿命(健康水平)
• 气泡大小:人口数量
• 颜色:所属洲际
• 拖动年份滑块观察全球发展趋势
• X轴:人均GDP(财富水平,对数刻度)
• Y轴:预期寿命(健康水平)
• 气泡大小:人口数量
• 颜色:所属洲际
• 拖动年份滑块观察全球发展趋势
7.6 正态分布68-95-99.7法则
散点验证正态分布的统计规律
1001000
1σ 内(±1个标准差)
42.8%
理论值:68.27%
214 / 500 个点
2σ 内(±2个标准差)
88.0%
理论值:95.45%
440 / 500 个点
3σ 内(±3个标准差)
99.0%
理论值:99.73%
495 / 500 个点
Python代码:
import numpy as np
import matplotlib.pyplot as plt
# 生成二元正态分布数据
n = 500
data = np.random.randn(n, 2) # 标准正态分布
distance = np.sqrt(data[:, 0]**2 + data[:, 1]**2)
# 计算各区间比例
within_1sigma = np.sum(distance <= 1) / n * 100
within_2sigma = np.sum(distance <= 2) / n * 100
within_3sigma = np.sum(distance <= 3) / n * 100
print(f"1σ内: {within_1sigma:.1f}% (理论68.27%)")
print(f"2σ内: {within_2sigma:.1f}% (理论95.45%)")
print(f"3σ内: {within_3sigma:.1f}% (理论99.73%)")
# 绘制散点图
plt.scatter(data[:, 0], data[:, 1],
c=distance, cmap='RdYlBu_r', alpha=0.6)
plt.colorbar(label='Distance from origin (σ)')
plt.title('68-95-99.7 Rule Visualization')
plt.show()💡 68-95-99.7法则:
• ■ 蓝色点:在1个标准差内(约68%的数据)
• ■ 绿色点:在1-2个标准差之间(约27%的数据)
• ■ 橙色点:在2-3个标准差之间(约4%的数据)
• ■ 红色点:在3个标准差之外(约0.3%的数据)
• 增加样本数可以看到实际分布更接近理论值
• ■ 蓝色点:在1个标准差内(约68%的数据)
• ■ 绿色点:在1-2个标准差之间(约27%的数据)
• ■ 橙色点:在2-3个标准差之间(约4%的数据)
• ■ 红色点:在3个标准差之外(约0.3%的数据)
• 增加样本数可以看到实际分布更接近理论值
7.7 估算圆周率:蒙特卡洛方法
通过随机撒点统计估算π的值,观察收敛过程
🎲 蒙特卡洛动画器(Monte Carlo Animator)
观察随机撒点过程,理解统计估算原理
步骤: 0 / 1000
速度1x
目标点数1000
🔍 观察要点
- • 注意蓝色点(圆内)和橙色点(圆外)的比例
- • 观察π估计值如何随点数增加而收敛
- • 点数越多,估计越准确(误差↓)
- • 暂停后可以仔细查看当前状态
📊 实时统计
总点数0
圆内点数0
圆外点数0
圆内比例0%
🎯 π 估计值
0.00000
真实值: π = 3.14159...
绝对误差3.14159
相对误差100.00%
计算公式:
π ≈ 4 × (圆内点数 / 总点数)
π ≈ 4 × (0 / 0)
π ≈ 0.00000
π ≈ 4 × (0 / 0)
π ≈ 0.00000
📚 蒙特卡洛方法原理
1️⃣
生成随机点
在[-1,1]×[-1,1]正方形内均匀撒点
2️⃣
判断内外
计算距离: d = √(x²+y²)
若 d ≤ 1 则在圆内
若 d ≤ 1 则在圆内
3️⃣
统计估算
π ≈ 4 × (圆内点数 / 总点数)
🎓 为什么这个方法有效?
• 圆面积 = π × r² = π × 1² = π
• 正方形面积 = (2r)² = 4
• 圆/正方形面积比 = π/4
• 均匀撒点时,圆内点数比例 ≈ π/4
• 因此:π ≈ 4 × (圆内点数/总点数)
Python绘图代码(蒙特卡洛模拟)
# 蒙特卡洛方法估计π(使用scatter绘图)
import matplotlib.pyplot as plt
import numpy as np
# 生成随机点
n_points = 10000
x = np.random.uniform(-1, 1, n_points)
y = np.random.uniform(-1, 1, n_points)
# 判断是否在单位圆内
inside = (x**2 + y**2) <= 1
# 创建图形
fig, ax = plt.subplots(figsize=(6, 6))
# 绘制圆内的点(蓝色)
plt.scatter(x[inside], y[inside],
c='#3b82f6', s=1, alpha=0.6, label='圆内')
# 绘制圆外的点(红色)
plt.scatter(x[~inside], y[~inside],
c='#ef4444', s=1, alpha=0.6, label='圆外')
# 绘制单位圆
circle = plt.Circle((0, 0), 1,
color='gray',
fill=False,
linewidth=2)
ax.add_patch(circle)
# 估计π
pi_estimate = 4 * np.sum(inside) / n_points
error = abs(pi_estimate - np.pi)
# 添加标题和标签
plt.title(f'蒙特卡洛估计π\n'
f'π ≈ {pi_estimate:.6f} (误差: {error:.6f})',
fontsize=12)
plt.xlabel('X')
plt.ylabel('Y')
plt.axis('equal')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper right')
plt.xlim(-1.1, 1.1)
plt.ylim(-1.1, 1.1)
plt.show()
# 关键学习点:
# 1. scatter()绘制大量散点:用c参数控制颜色
# 2. 布尔索引:inside和~inside分离数据
# 3. 蒙特卡洛方法:随机采样估计π
# 4. 样本量越大,估计越准确📚 章节总结
工具对比
- ✓ Matplotlib:基础灵活,适合科学绘图
- ✓ Seaborn:高级API,自动配色和样式
- ✓ Plotly:交互式,适合探索性分析
可视化编码
- ✓ 位置(x, y):主要数据维度
- ✓ 颜色(hue):分类或连续变量
- ✓ 大小(size):数值大小
- ✓ 形状(marker):分类标签