← 返回Book 2目录
第07章

散点图

Scatter Plots · 数据分布的直观展示

从基础到高级,掌握matplotlib、seaborn、plotly三大工具

📊 章节概览

散点图是最基础也最重要的数据可视化方法之一。本章系统学习三大Python可视化库的散点图绘制方法, 并通过鸢尾花数据集、正态分布、蒙特卡洛方法等实际案例,掌握散点图的应用技巧。

📐 Matplotlib
基础散点图、网格与随机分布
🌺 Seaborn
高级API、自动配色与分组
📈 Plotly
交互式气泡图与动态探索

7.1 Matplotlib散点图:规则网格 vs 随机散点

使用pyplot.scatter()绘制不同分布的散点

10400
02468100246810X AxisY Axis
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():基础散点图绘制方法,支持颜色、大小、透明度等参数

7.2 Seaborn鸢尾花散点图:多维数据可视化

使用seaborn.scatterplot()展示鸢尾花数据集

4.05.06.07.08.02.02.63.33.94.5花萼长度花萼宽度setosa 花萼长度: 5.45 花萼宽度: 3.47setosa 花萼长度: 5.55 花萼宽度: 3.50setosa 花萼长度: 5.30 花萼宽度: 3.78setosa 花萼长度: 5.01 花萼宽度: 3.58setosa 花萼长度: 5.36 花萼宽度: 3.76setosa 花萼长度: 5.60 花萼宽度: 3.79setosa 花萼长度: 5.22 花萼宽度: 3.51setosa 花萼长度: 5.02 花萼宽度: 3.42setosa 花萼长度: 5.27 花萼宽度: 3.64setosa 花萼长度: 5.65 花萼宽度: 3.45setosa 花萼长度: 5.78 花萼宽度: 3.74setosa 花萼长度: 5.20 花萼宽度: 3.71setosa 花萼长度: 5.51 花萼宽度: 3.53setosa 花萼长度: 5.36 花萼宽度: 3.61setosa 花萼长度: 5.62 花萼宽度: 3.46versicolor 花萼长度: 6.14 花萼宽度: 2.89versicolor 花萼长度: 6.30 花萼宽度: 2.87versicolor 花萼长度: 6.21 花萼宽度: 2.98versicolor 花萼长度: 6.00 花萼宽度: 2.92versicolor 花萼长度: 6.27 花萼宽度: 2.76versicolor 花萼长度: 6.55 花萼宽度: 2.92versicolor 花萼长度: 6.07 花萼宽度: 2.70versicolor 花萼长度: 6.07 花萼宽度: 2.78versicolor 花萼长度: 5.93 花萼宽度: 2.79versicolor 花萼长度: 6.56 花萼宽度: 3.05versicolor 花萼长度: 6.17 花萼宽度: 2.99versicolor 花萼长度: 6.05 花萼宽度: 2.87versicolor 花萼长度: 6.41 花萼宽度: 2.75versicolor 花萼长度: 5.91 花萼宽度: 2.70versicolor 花萼长度: 6.47 花萼宽度: 2.76virginica 花萼长度: 7.19 花萼宽度: 3.01virginica 花萼长度: 6.66 花萼宽度: 3.17virginica 花萼长度: 6.72 花萼宽度: 3.20virginica 花萼长度: 6.69 花萼宽度: 3.07virginica 花萼长度: 6.84 花萼宽度: 3.01virginica 花萼长度: 6.74 花萼宽度: 3.08virginica 花萼长度: 6.64 花萼宽度: 3.15virginica 花萼长度: 6.73 花萼宽度: 3.30virginica 花萼长度: 7.01 花萼宽度: 3.27virginica 花萼长度: 6.69 花萼宽度: 3.30virginica 花萼长度: 6.59 花萼宽度: 3.19virginica 花萼长度: 6.66 花萼宽度: 3.33virginica 花萼长度: 6.81 花萼宽度: 3.30virginica 花萼长度: 6.56 花萼宽度: 3.31virginica 花萼长度: 7.05 花萼宽度: 3.22物种山鸢尾变色鸢尾维吉尼亚鸢尾
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,代码更简洁
• 自动生成图例

7.3 散点包络线:ConvexHull凸包可视化

计算并显示散点集合的凸包边界

550
02468100246810(8.89, 3.59) 凸包顶点(7.83, 6.91)(7.43, 3.89)(5.41, 7.34)(7.76, 8.16)(8.17, 7.67)(5.92, 2.88)(8.22, 8.76) 凸包顶点(7.45, 3.69)(6.37, 2.67) 凸包顶点(6.83, 8.26)(1.93, 8.14) 凸包顶点(8.11, 8.91) 凸包顶点(3.91, 6.31)(3.33, 4.13)(5.15, 4.85)(2.06, 4.16) 凸包顶点(7.83, 2.49) 凸包顶点(6.54, 4.46)(1.60, 5.38) 凸包顶点内部点凸包顶点
总点数
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)

7.5 Plotly气泡图:Gapminder数据可视化

探索全球健康、财富与人口的关系演变

19602020
$500$1k$5k$10k$50k304050607080GDP per Capita (对数刻度)Life Expectancy (years)China GDP: $10500 预期寿命: 65岁 人口: 1150MIndia GDP: $5067 预期寿命: 60岁 人口: 1083MUSA GDP: $45000 预期寿命: 76.7岁 人口: 280MBrazil GDP: $10333 预期寿命: 68.3岁 人口: 163MJapan GDP: $29333 预期寿命: 78.7岁 人口: 115MGermany GDP: $34000 预期寿命: 77岁 人口: 80MUK GDP: $32333 预期寿命: 77.7岁 人口: 62MFrance GDP: $32833 预期寿命: 78岁 人口: 60MNigeria GDP: $3633 预期寿命: 50岁 人口: 152MEgypt GDP: $4400 预期寿命: 61.7岁 人口: 76M洲际亚洲美洲欧洲非洲
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轴:预期寿命(健康水平)
• 气泡大小:人口数量
• 颜色:所属洲际
• 拖动年份滑块观察全球发展趋势

7.6 正态分布68-95-99.7法则

散点验证正态分布的统计规律

1001000
3σ2σ1σ距离原点: 0.58σ距离原点: 1.70σ距离原点: 0.91σ距离原点: 1.39σ距离原点: 0.86σ距离原点: 0.71σ距离原点: 0.80σ距离原点: 1.24σ距离原点: 0.50σ距离原点: 2.37σ距离原点: 0.90σ距离原点: 1.04σ距离原点: 1.60σ距离原点: 1.69σ距离原点: 1.82σ距离原点: 1.41σ距离原点: 1.04σ距离原点: 0.65σ距离原点: 1.27σ距离原点: 1.66σ距离原点: 1.52σ距离原点: 0.23σ距离原点: 0.49σ距离原点: 0.38σ距离原点: 1.21σ距离原点: 1.56σ距离原点: 1.70σ距离原点: 2.03σ距离原点: 1.80σ距离原点: 1.11σ距离原点: 0.86σ距离原点: 2.37σ距离原点: 0.74σ距离原点: 0.81σ距离原点: 1.74σ距离原点: 1.77σ距离原点: 1.24σ距离原点: 0.65σ距离原点: 2.47σ距离原点: 2.56σ距离原点: 0.77σ距离原点: 0.06σ距离原点: 0.94σ距离原点: 0.47σ距离原点: 2.70σ距离原点: 0.63σ距离原点: 1.07σ距离原点: 0.90σ距离原点: 0.60σ距离原点: 1.33σ距离原点: 2.56σ距离原点: 0.54σ距离原点: 0.15σ距离原点: 0.38σ距离原点: 1.21σ距离原点: 0.36σ距离原点: 0.88σ距离原点: 1.74σ距离原点: 1.79σ距离原点: 0.29σ距离原点: 0.48σ距离原点: 0.78σ距离原点: 0.74σ距离原点: 1.39σ距离原点: 0.95σ距离原点: 1.06σ距离原点: 0.72σ距离原点: 0.95σ距离原点: 1.02σ距离原点: 1.32σ距离原点: 0.90σ距离原点: 0.87σ距离原点: 0.93σ距离原点: 0.90σ距离原点: 0.81σ距离原点: 1.23σ距离原点: 0.60σ距离原点: 1.54σ距离原点: 0.59σ距离原点: 0.62σ距离原点: 2.15σ距离原点: 1.41σ距离原点: 0.59σ距离原点: 1.81σ距离原点: 1.70σ距离原点: 0.93σ距离原点: 1.32σ距离原点: 1.65σ距离原点: 2.65σ距离原点: 1.20σ距离原点: 0.79σ距离原点: 3.15σ距离原点: 1.26σ距离原点: 1.45σ距离原点: 0.46σ距离原点: 1.31σ距离原点: 1.47σ距离原点: 1.47σ距离原点: 2.89σ距离原点: 1.88σ距离原点: 1.61σ距离原点: 2.04σ距离原点: 2.39σ距离原点: 1.04σ距离原点: 0.50σ距离原点: 0.46σ距离原点: 0.64σ距离原点: 1.98σ距离原点: 1.12σ距离原点: 0.81σ距离原点: 1.97σ距离原点: 0.97σ距离原点: 0.73σ距离原点: 1.21σ距离原点: 0.94σ距离原点: 0.99σ距离原点: 1.36σ距离原点: 0.90σ距离原点: 1.69σ距离原点: 1.25σ距离原点: 1.82σ距离原点: 1.26σ距离原点: 1.17σ距离原点: 0.95σ距离原点: 0.77σ距离原点: 2.70σ距离原点: 1.00σ距离原点: 0.71σ距离原点: 1.86σ距离原点: 0.94σ距离原点: 1.00σ距离原点: 2.05σ距离原点: 2.90σ距离原点: 1.03σ距离原点: 0.47σ距离原点: 1.32σ距离原点: 1.79σ距离原点: 0.87σ距离原点: 0.52σ距离原点: 2.21σ距离原点: 1.54σ距离原点: 0.72σ距离原点: 0.77σ距离原点: 1.27σ距离原点: 1.41σ距离原点: 2.67σ距离原点: 1.32σ距离原点: 1.73σ距离原点: 0.98σ距离原点: 0.87σ距离原点: 0.48σ距离原点: 2.26σ距离原点: 1.61σ距离原点: 1.98σ距离原点: 0.97σ距离原点: 0.54σ距离原点: 0.53σ距离原点: 0.42σ距离原点: 1.45σ距离原点: 1.35σ距离原点: 0.78σ距离原点: 1.35σ距离原点: 1.10σ距离原点: 1.94σ距离原点: 1.55σ距离原点: 0.50σ距离原点: 0.25σ距离原点: 0.24σ距离原点: 0.77σ距离原点: 1.02σ距离原点: 0.54σ距离原点: 1.02σ距离原点: 1.18σ距离原点: 1.55σ距离原点: 1.28σ距离原点: 2.32σ距离原点: 0.61σ距离原点: 0.42σ距离原点: 0.23σ距离原点: 1.21σ距离原点: 0.90σ距离原点: 3.29σ距离原点: 0.43σ距离原点: 1.67σ距离原点: 1.27σ距离原点: 2.24σ距离原点: 0.72σ距离原点: 2.34σ距离原点: 0.60σ距离原点: 0.72σ距离原点: 0.92σ距离原点: 0.75σ距离原点: 0.91σ距离原点: 2.83σ距离原点: 0.27σ距离原点: 1.05σ距离原点: 0.21σ距离原点: 1.19σ距离原点: 2.91σ距离原点: 1.37σ距离原点: 1.40σ距离原点: 0.22σ距离原点: 1.75σ距离原点: 1.70σ距离原点: 1.80σ距离原点: 0.38σ距离原点: 0.03σ距离原点: 0.57σ距离原点: 1.85σ距离原点: 2.34σ距离原点: 0.62σ距离原点: 0.96σ距离原点: 1.41σ距离原点: 2.41σ距离原点: 1.37σ距离原点: 2.14σ距离原点: 2.49σ距离原点: 1.27σ距离原点: 1.72σ距离原点: 1.26σ距离原点: 1.50σ距离原点: 0.82σ距离原点: 1.94σ距离原点: 1.02σ距离原点: 0.35σ距离原点: 1.36σ距离原点: 1.41σ距离原点: 0.52σ距离原点: 0.73σ距离原点: 1.01σ距离原点: 1.41σ距离原点: 0.40σ距离原点: 0.42σ距离原点: 1.65σ距离原点: 0.66σ距离原点: 0.62σ距离原点: 1.12σ距离原点: 0.76σ距离原点: 2.69σ距离原点: 2.16σ距离原点: 1.38σ距离原点: 1.31σ距离原点: 1.28σ距离原点: 1.36σ距离原点: 1.14σ距离原点: 1.28σ距离原点: 0.58σ距离原点: 0.96σ距离原点: 1.41σ距离原点: 0.97σ距离原点: 0.69σ距离原点: 2.44σ距离原点: 2.39σ距离原点: 1.14σ距离原点: 2.38σ距离原点: 1.13σ距离原点: 0.71σ距离原点: 2.08σ距离原点: 0.84σ距离原点: 1.34σ距离原点: 0.89σ距离原点: 0.97σ距离原点: 0.88σ距离原点: 1.24σ距离原点: 2.70σ距离原点: 0.86σ距离原点: 0.16σ距离原点: 1.49σ距离原点: 1.36σ距离原点: 0.92σ距离原点: 0.77σ距离原点: 2.21σ距离原点: 2.70σ距离原点: 0.72σ距离原点: 1.80σ距离原点: 2.54σ距离原点: 0.29σ距离原点: 0.54σ距离原点: 1.87σ距离原点: 0.74σ距离原点: 0.62σ距离原点: 1.67σ距离原点: 1.83σ距离原点: 0.76σ距离原点: 1.16σ距离原点: 1.25σ距离原点: 1.42σ距离原点: 1.42σ距离原点: 0.74σ距离原点: 1.06σ距离原点: 0.60σ距离原点: 0.98σ距离原点: 0.31σ距离原点: 1.46σ距离原点: 0.67σ距离原点: 0.32σ距离原点: 0.80σ距离原点: 0.48σ距离原点: 0.49σ距离原点: 1.23σ距离原点: 0.22σ距离原点: 1.39σ距离原点: 0.30σ距离原点: 1.39σ距离原点: 0.48σ距离原点: 1.58σ距离原点: 1.50σ距离原点: 0.96σ距离原点: 0.47σ距离原点: 1.50σ距离原点: 1.54σ距离原点: 1.97σ距离原点: 1.70σ距离原点: 0.74σ距离原点: 1.87σ距离原点: 0.40σ距离原点: 0.59σ距离原点: 1.40σ距离原点: 1.00σ距离原点: 2.03σ距离原点: 2.24σ距离原点: 1.67σ距离原点: 1.55σ距离原点: 1.75σ距离原点: 1.06σ距离原点: 0.38σ距离原点: 1.46σ距离原点: 2.28σ距离原点: 1.06σ距离原点: 0.87σ距离原点: 1.06σ距离原点: 1.62σ距离原点: 0.82σ距离原点: 1.51σ距离原点: 0.53σ距离原点: 0.73σ距离原点: 2.59σ距离原点: 1.80σ距离原点: 1.48σ距离原点: 1.08σ距离原点: 0.91σ距离原点: 0.77σ距离原点: 0.58σ距离原点: 1.36σ距离原点: 2.18σ距离原点: 1.89σ距离原点: 1.95σ距离原点: 0.73σ距离原点: 0.39σ距离原点: 2.09σ距离原点: 0.26σ距离原点: 0.49σ距离原点: 0.93σ距离原点: 0.29σ距离原点: 0.56σ距离原点: 1.76σ距离原点: 0.41σ距离原点: 1.44σ距离原点: 1.74σ距离原点: 0.50σ距离原点: 1.04σ距离原点: 0.67σ距离原点: 0.41σ距离原点: 0.84σ距离原点: 0.56σ距离原点: 1.70σ距离原点: 0.94σ距离原点: 0.83σ距离原点: 0.98σ距离原点: 1.35σ距离原点: 0.38σ距离原点: 1.34σ距离原点: 1.96σ距离原点: 1.85σ距离原点: 1.41σ距离原点: 2.51σ距离原点: 1.47σ距离原点: 1.60σ距离原点: 1.14σ距离原点: 0.66σ距离原点: 0.29σ距离原点: 1.76σ距离原点: 0.15σ距离原点: 0.62σ距离原点: 1.09σ距离原点: 0.91σ距离原点: 1.15σ距离原点: 1.15σ距离原点: 0.65σ距离原点: 2.38σ距离原点: 2.40σ距离原点: 0.60σ距离原点: 1.65σ距离原点: 0.73σ距离原点: 1.10σ距离原点: 1.83σ距离原点: 1.34σ距离原点: 1.35σ距离原点: 0.20σ距离原点: 1.59σ距离原点: 1.53σ距离原点: 1.96σ距离原点: 2.41σ距离原点: 0.43σ距离原点: 1.55σ距离原点: 1.28σ距离原点: 0.08σ距离原点: 2.20σ距离原点: 0.91σ距离原点: 0.31σ距离原点: 1.06σ距离原点: 0.78σ距离原点: 1.88σ距离原点: 2.27σ距离原点: 1.02σ距离原点: 1.40σ距离原点: 1.03σ距离原点: 0.20σ距离原点: 3.25σ距离原点: 0.62σ距离原点: 0.22σ距离原点: 1.00σ距离原点: 1.09σ距离原点: 1.80σ距离原点: 1.85σ距离原点: 1.98σ距离原点: 1.02σ距离原点: 0.21σ距离原点: 0.66σ距离原点: 0.58σ距离原点: 0.93σ距离原点: 2.72σ距离原点: 1.41σ距离原点: 1.65σ距离原点: 2.67σ距离原点: 1.49σ距离原点: 0.55σ距离原点: 2.26σ距离原点: 0.36σ距离原点: 0.97σ距离原点: 1.95σ距离原点: 1.83σ距离原点: 1.78σ距离原点: 1.42σ距离原点: 0.31σ距离原点: 1.63σ距离原点: 0.80σ距离原点: 0.52σ距离原点: 0.73σ距离原点: 1.39σ距离原点: 1.21σ距离原点: 1.52σ距离原点: 1.91σ距离原点: 2.28σ距离原点: 2.54σ距离原点: 1.68σ距离原点: 0.66σ距离原点: 1.09σ距离原点: 1.27σ距离原点: 1.30σ距离原点: 0.94σ距离原点: 0.75σ距离原点: 0.86σ距离原点: 1.24σ距离原点: 0.31σ距离原点: 0.81σ距离原点: 0.14σ距离原点: 1.16σ距离原点: 1.92σ距离原点: 1.73σ距离原点: 1.09σ距离原点: 1.73σ距离原点: 1.86σ距离原点: 1.54σ距离原点: 0.74σ距离原点: 1.39σ距离原点: 0.49σ距离原点: 1.21σ距离原点: 1.77σ距离原点: 1.30σ距离原点: 0.75σ距离原点: 1.79σ距离原点: 1.28σ距离原点: 0.46σ距离原点: 0.57σ距离原点: 0.40σ距离原点: 0.66σ距离原点: 0.98σ距离原点: 2.47σ距离原点: 1.13σ距离原点: 0.34σ距离原点: 3.32σ距离原点: 1.43σ距离原点: 1.65σ距离原点: 0.66σ距离原点: 1.14σ距离原点: 0.35σ距离原点: 0.41σ距离原点: 1.49σμ
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%的数据)
• 增加样本数可以看到实际分布更接近理论值

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

📚 蒙特卡洛方法原理

1️⃣
生成随机点
在[-1,1]×[-1,1]正方形内均匀撒点
2️⃣
判断内外
计算距离: d = √(x²+y²)
若 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):分类标签