Matplotlib绘制正态分布图:使用NumPy和Matplotlib实现数据可视化
参考:Normal Distribution Plot using Numpy and Matplotlib
正态分布,也称为高斯分布,是统计学和概率论中最重要的概率分布之一。它在自然科学、社会科学和工程领域中广泛应用,用于描述许多自然现象和随机变量的分布。在数据分析和可视化中,能够准确地绘制和理解正态分布图是一项重要技能。本文将详细介绍如何使用Python的NumPy和Matplotlib库来绘制正态分布图,并通过多个示例展示不同的绘图技巧和customization选项。
1. 正态分布的基本概念
在深入绘图之前,我们先简要回顾一下正态分布的基本概念。正态分布是一种连续概率分布,其概率密度函数呈钟形曲线,也称为”钟形曲线”。正态分布由两个参数决定:
- μ(均值):分布的中心位置
- σ(标准差):分布的分散程度
标准正态分布是均值为0,标准差为1的特殊情况。
下面是一个使用NumPy和Matplotlib绘制标准正态分布的基本示例:
import numpy as np
import matplotlib.pyplot as plt
# 生成x轴数据
x = np.linspace(-4, 4, 100)
# 计算正态分布的概率密度
y = 1 / (np.sqrt(2 * np.pi)) * np.exp(-x**2 / 2)
# 绘制图形
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='Standard Normal Distribution')
plt.title('Standard Normal Distribution - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.grid(True)
plt.show()
Output:
这个示例展示了如何使用NumPy生成数据点,并使用Matplotlib绘制标准正态分布曲线。我们使用np.linspace()
函数生成x轴数据,然后使用正态分布的概率密度函数计算y值。最后,使用plt.plot()
函数绘制曲线。
2. 使用NumPy的random模块生成正态分布数据
NumPy的random模块提供了生成符合正态分布的随机数的功能。我们可以使用这些随机数来创建直方图,以可视化正态分布的特征。
import numpy as np
import matplotlib.pyplot as plt
# 生成正态分布随机数
mu, sigma = 0, 1 # 均值和标准差
data = np.random.normal(mu, sigma, 10000)
# 绘制直方图
plt.figure(figsize=(10, 6))
plt.hist(data, bins=50, density=True, alpha=0.7, color='skyblue')
plt.title('Normal Distribution Histogram - how2matplotlib.com')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.grid(True)
plt.show()
Output:
在这个示例中,我们使用np.random.normal()
函数生成10000个符合正态分布的随机数。然后,我们使用plt.hist()
函数绘制这些数据的直方图。density=True
参数确保直方图显示的是概率密度而不是计数。
3. 比较不同参数的正态分布
通过改变均值和标准差,我们可以观察正态分布的变化。下面的示例展示了如何在同一图表中比较不同参数的正态分布:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 100)
# 定义不同参数的正态分布
distributions = [
(0, 1, 'Standard Normal'),
(0, 2, 'Wide Normal'),
(2, 1, 'Shifted Normal'),
]
plt.figure(figsize=(12, 8))
for mu, sigma, name in distributions:
y = 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(-(x - mu)**2 / (2 * sigma**2))
plt.plot(x, y, label=f'{name} (μ={mu}, σ={sigma})')
plt.title('Comparison of Normal Distributions - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.grid(True)
plt.show()
Output:
这个示例展示了如何绘制和比较具有不同均值和标准差的正态分布。我们使用循环来绘制多个分布,并使用不同的颜色和标签来区分它们。
4. 添加累积分布函数(CDF)
除了概率密度函数(PDF),累积分布函数(CDF)也是描述正态分布的重要工具。以下示例展示了如何在同一图表中绘制PDF和CDF:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.linspace(-4, 4, 100)
pdf = norm.pdf(x)
cdf = norm.cdf(x)
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.plot(x, pdf, 'b-', label='PDF')
plt.title('Probability Density Function - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(x, cdf, 'r-', label='CDF')
plt.title('Cumulative Distribution Function - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Cumulative Probability')
plt.legend()
plt.tight_layout()
plt.show()
Output:
这个示例使用了SciPy的norm
模块来计算PDF和CDF。我们使用plt.subplot()
函数在同一图表中创建两个子图,分别显示PDF和CDF。
5. 3D正态分布图
我们还可以创建3D正态分布图,以更直观地展示二维正态分布的特征:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def multivariate_normal(x, y, x0, y0, sigmax, sigmay, rho):
z = (x-x0)**2/sigmax**2 + (y-y0)**2/sigmay**2 - 2*rho*(x-x0)*(y-y0)/(sigmax*sigmay)
return np.exp(-z/(2*(1-rho**2))) / (2*np.pi*sigmax*sigmay*np.sqrt(1-rho**2))
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = multivariate_normal(X, Y, 0, 0, 1, 1, 0)
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap='viridis')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Probability Density')
ax.set_title('3D Normal Distribution - how2matplotlib.com')
plt.colorbar(surf)
plt.show()
Output:
这个示例展示了如何创建二维正态分布的3D表面图。我们定义了一个multivariate_normal
函数来计算二维正态分布的概率密度,然后使用plot_surface()
函数绘制3D表面。
6. 正态分布的置信区间
在统计分析中,置信区间是一个重要概念。以下示例展示了如何在正态分布图上标注不同的置信区间:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.linspace(-4, 4, 1000)
y = norm.pdf(x)
plt.figure(figsize=(12, 6))
plt.plot(x, y, 'b-', label='PDF')
# 标注置信区间
intervals = [
(0.68, 'green', '68% CI'),
(0.95, 'orange', '95% CI'),
(0.99, 'red', '99% CI')
]
for interval, color, label in intervals:
left = norm.ppf((1 - interval) / 2)
right = norm.ppf((1 + interval) / 2)
plt.fill_between(x, y, where=(x > left) & (x < right), color=color, alpha=0.3, label=label)
plt.title('Normal Distribution with Confidence Intervals - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.grid(True)
plt.show()
Output:
这个示例使用plt.fill_between()
函数来填充不同置信区间的区域。我们使用norm.ppf()
函数计算每个置信区间的边界。
7. Q-Q图(Quantile-Quantile Plot)
Q-Q图是用于比较两个概率分布的图形方法。它常用于检验数据是否符合正态分布。以下是一个创建Q-Q图的示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 生成正态分布数据
np.random.seed(0)
data = np.random.normal(0, 1, 1000)
# 创建Q-Q图
fig, ax = plt.subplots(figsize=(10, 6))
stats.probplot(data, dist="norm", plot=ax)
ax.set_title("Q-Q Plot - how2matplotlib.com")
ax.set_xlabel("Theoretical Quantiles")
ax.set_ylabel("Sample Quantiles")
plt.grid(True)
plt.show()
Output:
这个示例使用SciPy的stats.probplot()
函数创建Q-Q图。如果数据点大致落在对角线上,则表明数据符合正态分布。
8. 正态分布的箱线图
箱线图(Box Plot)是另一种用于可视化数据分布的有效工具。以下示例展示了如何创建正态分布数据的箱线图:
import numpy as np
import matplotlib.pyplot as plt
# 生成多组正态分布数据
np.random.seed(0)
data = [np.random.normal(0, std, 100) for std in range(1, 4)]
plt.figure(figsize=(10, 6))
plt.boxplot(data, labels=['σ=1', 'σ=2', 'σ=3'])
plt.title('Box Plot of Normal Distributions - how2matplotlib.com')
plt.ylabel('Value')
plt.grid(True)
plt.show()
Output:
这个示例生成了三组具有不同标准差的正态分布数据,并使用plt.boxplot()
函数创建箱线图。箱线图显示了数据的中位数、四分位数范围和异常值。
9. 正态分布的核密度估计
核密度估计(Kernel Density Estimation, KDE)是一种非参数方法,用于估计随机变量的概率密度函数。它可以用来平滑地表示数据分布。以下是一个使用KDE的示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 生成正态分布数据
np.random.seed(0)
data = np.random.normal(0, 1, 1000)
# 计算KDE
kde = stats.gaussian_kde(data)
x_range = np.linspace(data.min(), data.max(), 100)
plt.figure(figsize=(10, 6))
plt.hist(data, bins=30, density=True, alpha=0.7, label='Histogram')
plt.plot(x_range, kde(x_range), 'r-', label='KDE')
plt.title('Normal Distribution: Histogram vs KDE - how2matplotlib.com')
plt.xlabel('Value')
plt.ylabel('Density')
plt.legend()
plt.grid(True)
plt.show()
Output:
这个示例使用scipy.stats.gaussian_kde()
函数计算KDE,并将其与直方图进行比较。KDE提供了数据分布的平滑估计。
10. 正态分布的概率图
概率图是另一种用于评估数据是否符合特定分布的图形方法。以下是创建正态概率图的示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# 生成正态分布数据
np.random.seed(0)
data = np.random.normal(0, 1, 1000)
# 创建概率图
fig, ax = plt.subplots(figsize=(10, 6))
res = stats.probplot(data, plot=ax)
ax.set_title("Normal Probability Plot - how2matplotlib.com")
ax.set_xlabel("Theoretical Quantiles")
ax.set_ylabel("Ordered Values")
plt.grid(True)
plt.show()
Output:
这个示例使用scipy.stats.probplot()
函数创建正态概率图。如果数据点大致落在直线上,则表明数据符合正态分布。
11. 多个正态分布的叠加图
有时我们需要在同一图表中比较多个正态分布。以下示例展示了如何创建多个正态分布的叠加图:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x = np.linspace(-5, 5, 100)
distributions = [
(0, 1, 'blue', 'μ=0, σ=1'),
(0, 0.5, 'red', 'μ=0, σ=0.5'),
(1, 1, 'green', 'μ=1, σ=1'),
]
plt.figure(figsize=(12, 6))
for mu, sigma, color, label in distributions:
y = stats.norm.pdf(x, mu, sigma)
plt.plotplt.plot(x, y, color=color, label=label)
plt.title('Multiple Normal Distributions - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.grid(True)
plt.show()
这个示例展示了如何在同一图表中绘制多个具有不同参数的正态分布。我们使用不同的颜色和标签来区分每个分布,使得比较更加直观。
12. 正态分布的区域填充
在某些情况下,我们可能需要强调正态分布的特定区域。以下示例展示了如何填充正态分布曲线下的特定区域:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x = np.linspace(-4, 4, 100)
y = stats.norm.pdf(x)
plt.figure(figsize=(12, 6))
plt.plot(x, y, 'b-', label='Normal Distribution')
# 填充-1到1之间的区域
fill_x = np.linspace(-1, 1, 100)
fill_y = stats.norm.pdf(fill_x)
plt.fill_between(fill_x, fill_y, color='red', alpha=0.3, label='68% Confidence Interval')
plt.title('Normal Distribution with Filled Area - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Probability Density')
plt.legend()
plt.grid(True)
plt.show()
Output:
这个示例使用plt.fill_between()
函数来填充正态分布曲线下的特定区域。在这里,我们填充了表示68%置信区间的-1到1之间的区域。
13. 正态分布的动画
创建动画可以帮助我们更好地理解正态分布的特性。以下是一个简单的动画示例,展示了标准差变化对正态分布形状的影响:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x = np.linspace(-5, 5, 100)
fig, ax = plt.subplots(figsize=(10, 6))
line, = ax.plot([], [], 'b-', lw=2)
ax.set_xlim(-5, 5)
ax.set_ylim(0, 1)
ax.set_title('Normal Distribution Animation - how2matplotlib.com')
ax.set_xlabel('X')
ax.set_ylabel('Probability Density')
def init():
line.set_data([], [])
return line,
def animate(i):
sigma = 0.5 + i * 0.05
y = 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(-(x**2) / (2 * sigma**2))
line.set_data(x, y)
ax.set_title(f'Normal Distribution (σ={sigma:.2f}) - how2matplotlib.com')
return line,
anim = FuncAnimation(fig, animate, init_func=init, frames=30, interval=200, blit=True)
plt.show()
Output:
这个示例使用Matplotlib的FuncAnimation
类创建了一个动画,展示了标准差从0.5逐渐增加到2时正态分布形状的变化。
14. 正态分布的热图
热图可以用来可视化二维正态分布。以下是一个创建二维正态分布热图的示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x, y = np.mgrid[-3:3:.1, -3:3:.1]
pos = np.dstack((x, y))
rv = stats.multivariate_normal([0, 0], [[1, 0], [0, 1]])
plt.figure(figsize=(10, 8))
plt.imshow(rv.pdf(pos), cmap='viridis', extent=[-3, 3, -3, 3])
plt.colorbar(label='Probability Density')
plt.title('2D Normal Distribution Heatmap - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个示例使用scipy.stats.multivariate_normal
创建二维正态分布,然后使用plt.imshow()
函数将其可视化为热图。颜色越亮表示概率密度越高。
15. 正态分布的等高线图
等高线图是另一种可视化二维正态分布的方法。以下是一个创建等高线图的示例:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
x, y = np.mgrid[-3:3:.1, -3:3:.1]
pos = np.dstack((x, y))
rv = stats.multivariate_normal([0, 0], [[1, 0], [0, 1]])
plt.figure(figsize=(10, 8))
plt.contourf(x, y, rv.pdf(pos), cmap='viridis')
plt.colorbar(label='Probability Density')
plt.title('2D Normal Distribution Contour Plot - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个示例使用plt.contourf()
函数创建填充等高线图,展示了二维正态分布的概率密度。
结论
本文详细介绍了如何使用NumPy和Matplotlib绘制正态分布图。我们探讨了多种可视化技术,包括基本的概率密度函数图、直方图、3D图、Q-Q图、箱线图、核密度估计、概率图、多分布比较、区域填充、动画、热图和等高线图。这些技术不仅适用于正态分布,还可以应用于其他概率分布的可视化。
通过这些示例,我们可以看到Matplotlib提供了丰富的工具和选项来创建各种类型的统计图表。这些可视化方法可以帮助我们更好地理解和分析数据分布,特别是在处理大量数据或复杂统计模型时。
在实际应用中,选择合适的可视化方法取决于具体的数据特征和分析目的。例如,直方图和KDE适合观察整体分布形状,Q-Q图和概率图适合检验数据是否符合正态分布,而3D图和热图则适合展示二维分布的特征。
最后,值得注意的是,虽然本文主要关注正态分布,但这些可视化技术和方法同样适用于其他类型的概率分布。通过灵活运用这些工具,我们可以更有效地探索和理解各种统计数据,为数据分析和决策提供有力支持。