使用Matplotlib在Python中计算和绘制累积分布函数的全面指南

使用Matplotlib在Python中计算和绘制累积分布函数的全面指南

参考:How to calculate and plot a Cumulative Distribution function with Matplotlib in Python

累积分布函数(Cumulative Distribution Function,简称CDF)是概率论和统计学中的一个重要概念,它描述了随机变量小于或等于某个值的概率。在数据分析和可视化中,CDF是一个强大的工具,可以帮助我们理解数据的分布特征。本文将详细介绍如何使用Python的Matplotlib库来计算和绘制CDF,并提供多个实用示例。

1. 累积分布函数的基本概念

累积分布函数F(x)定义为随机变量X小于或等于x的概率:

F(x) = P(X ≤ x)

CDF具有以下特性:
– 单调递增
– 右连续
– 取值范围为[0, 1]
– 当x趋向负无穷时,F(x)趋向0;当x趋向正无穷时,F(x)趋向1

了解这些特性对于正确解释和使用CDF图表至关重要。

2. 准备工作:导入必要的库

在开始绘制CDF之前,我们需要导入必要的Python库。主要使用的库包括NumPy(用于数值计算)和Matplotlib(用于绘图)。

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

print("Welcome to how2matplotlib.com")

这段代码导入了所需的库,并设置了随机种子以确保结果的可重现性。

3. 生成示例数据

为了演示CDF的计算和绘制,我们需要一些示例数据。让我们生成一些随机数据:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

# 生成正态分布的随机数据
data = np.random.normal(loc=0, scale=1, size=1000)

print("Data from how2matplotlib.com:", data[:5])

这段代码生成了1000个服从标准正态分布(均值为0,标准差为1)的随机数。

4. 计算累积分布函数

计算CDF的一种简单方法是使用NumPy的cumsumsort函数:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

def calculate_cdf(data):
    sorted_data = np.sort(data)
    y = np.arange(1, len(data) + 1) / len(data)
    return sorted_data, y

x, y = calculate_cdf(data)

print("CDF data from how2matplotlib.com:")
print("x:", x[:5])
print("y:", y[:5])

这个函数首先对数据进行排序,然后计算每个数据点对应的累积概率。返回的x是排序后的数据,y是对应的累积概率。

5. 使用Matplotlib绘制基本的CDF图

现在我们有了CDF的数据,可以使用Matplotlib来绘制图表:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

plt.figure(figsize=(10, 6))
plt.plot(x, y, label='CDF')
plt.title('Cumulative Distribution Function')
plt.xlabel('Value')
plt.ylabel('Cumulative Probability')
plt.legend()
plt.grid(True)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这段代码创建了一个基本的CDF图。我们设置了图表的大小、标题、坐标轴标签,并添加了图例和网格线。

6. 美化CDF图表

为了使CDF图表更加美观和信息丰富,我们可以添加一些额外的元素:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

plt.figure(figsize=(12, 7))
plt.plot(x, y, 'b-', linewidth=2, label='CDF')
plt.fill_between(x, y, alpha=0.1)
plt.title('Enhanced Cumulative Distribution Function', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xlim(min(x), max(x))
plt.ylim(0, 1)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个增强版的CDF图添加了填充区域、调整了线条宽度、字体大小,并设置了x轴和y轴的范围。

7. 比较多个分布的CDF

在实际应用中,我们经常需要比较不同分布的CDF。让我们生成三个不同的正态分布并比较它们的CDF:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data1 = np.random.normal(0, 1, 1000)
data2 = np.random.normal(1, 1.5, 1000)
data3 = np.random.normal(-1, 0.5, 1000)

x1, y1 = calculate_cdf(data1)
x2, y2 = calculate_cdf(data2)
x3, y3 = calculate_cdf(data3)

plt.figure(figsize=(12, 7))
plt.plot(x1, y1, 'b-', label='Distribution 1')
plt.plot(x2, y2, 'r-', label='Distribution 2')
plt.plot(x3, y3, 'g-', label='Distribution 3')
plt.title('Comparison of CDFs for Different Distributions', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这段代码生成了三个不同参数的正态分布,计算它们的CDF,并在同一图表上绘制,便于比较。

8. 添加参考线和注释

为了更好地解释CDF图,我们可以添加参考线和注释:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

plt.figure(figsize=(12, 7))
plt.plot(x, y, 'b-', linewidth=2, label='CDF')
plt.axhline(y=0.5, color='r', linestyle='--', label='Median')
plt.axvline(x=np.median(data), color='g', linestyle='--', label='Median Value')
plt.title('CDF with Reference Lines', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.annotate('50% of data\nbelow this point', xy=(np.median(data), 0.5), xytext=(np.median(data)-2, 0.7),
             arrowprops=dict(facecolor='black', shrink=0.05))
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个示例添加了表示中位数的水平和垂直参考线,并用箭头注释标注了中位数的位置。

9. 使用阶梯图表示离散CDF

对于离散数据,使用阶梯图来表示CDF可能更合适:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

discrete_data = np.random.randint(1, 7, 1000)  # 模拟骰子投掷
x, y = calculate_cdf(discrete_data)

plt.figure(figsize=(12, 7))
plt.step(x, y, where='post', label='Discrete CDF')
plt.title('Discrete Cumulative Distribution Function', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(range(1, 7))
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个例子模拟了骰子投掷的结果,并使用阶梯图来表示离散CDF。

10. 绘制理论CDF与经验CDF的对比

在许多情况下,我们想要比较数据的经验CDF与理论CDF:

from scipy import stats
import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

# 生成正态分布数据
data = np.random.normal(0, 1, 1000)

# 计算经验CDF
x_emp, y_emp = calculate_cdf(data)

# 计算理论CDF
x_theo = np.linspace(min(data), max(data), 100)
y_theo = stats.norm.cdf(x_theo, 0, 1)

plt.figure(figsize=(12, 7))
plt.plot(x_emp, y_emp, 'b-', label='Empirical CDF')
plt.plot(x_theo, y_theo, 'r--', label='Theoretical CDF')
plt.title('Empirical vs Theoretical CDF', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个示例比较了生成的正态分布数据的经验CDF与理论CDF。

11. 使用子图比较多个CDF

当需要比较多个CDF时,使用子图可以提高可读性:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data1 = np.random.normal(0, 1, 1000)
data2 = np.random.exponential(1, 1000)
data3 = np.random.uniform(-2, 2, 1000)

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 6))

for ax, data, title in zip([ax1, ax2, ax3], [data1, data2, data3], ['Normal', 'Exponential', 'Uniform']):
    x, y = calculate_cdf(data)
    ax.plot(x, y)
    ax.set_title(f'{title} Distribution CDF')
    ax.set_xlabel('Value')
    ax.set_ylabel('Cumulative Probability')
    ax.grid(True)
    ax.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=ax.transAxes, alpha=0.2, fontsize=20)

plt.tight_layout()
plt.show()

这个例子创建了三个子图,分别显示正态分布、指数分布和均匀分布的CDF。

12. 添加置信区间

在某些应用中,添加置信区间可以提供额外的信息:

from scipy import stats
import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data = np.random.normal(0, 1, 1000)
x, y = calculate_cdf(data)

# 计算95%置信区间
ci = 0.95
n = len(data)
lower = y - 1.96 * np.sqrt(y * (1 - y) / n)
upper = y + 1.96 * np.sqrt(y * (1 - y) / n)

plt.figure(figsize=(12, 7))
plt.plot(x, y, 'b-', label='CDF')
plt.fill_between(x, lower, upper, alpha=0.2, label='95% CI')
plt.title('CDF with 95% Confidence Interval', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个示例计算并绘制了CDF的95%置信区间。

13. 使用对数刻度

对于跨越多个数量级的数据,使用对数刻度可能更合适:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data = np.random.lognormal(0, 1, 1000)
x, y = calculate_cdf(data)

plt.figure(figsize=(12, 7))
plt.semilogx(x, y, 'b-', label='CDF')
plt.title('CDF with Logarithmic X-axis', fontsize=16)
plt.xlabel('Value (log scale)', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个例子使用对数正态分布的数据,并在x轴使用对数刻度。

14. 绘制反向CDF(生存函数)

生存函数是CDF的补集,在某些领域(如可靠性分析)中很有用:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data = np.random.exponential(1, 1000)
x, y = calculate_cdf(data)

plt.figure(figsize=(12, 7))
plt.plot(x, 1 - y, 'b-', label='Survival Function')
plt.title('Survival Function (1 - CDF)', fontsize=16)plt.xlabel('Value', fontsize=12)
plt.ylabel('Survival Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个示例绘制了生存函数,它是CDF的补集(1 – CDF)。

15. 使用样式美化CDF图

Matplotlib提供了多种样式选项,可以使图表更加美观:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

plt.style.use('seaborn')

data = np.random.normal(0, 1, 1000)
x, y = calculate_cdf(data)

plt.figure(figsize=(12, 7))
plt.plot(x, y, 'b-', linewidth=2, label='CDF')
plt.title('Styled CDF Plot', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个例子使用了’seaborn’样式,使图表看起来更加现代和专业。

16. 绘制多个CDF并添加图例

当需要在同一图表上比较多个分布时,清晰的图例非常重要:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

distributions = {
    'Normal': np.random.normal(0, 1, 1000),
    'Exponential': np.random.exponential(1, 1000),
    'Uniform': np.random.uniform(-2, 2, 1000)
}

plt.figure(figsize=(12, 7))

for name, data in distributions.items():
    x, y = calculate_cdf(data)
    plt.plot(x, y, label=name)

plt.title('Comparison of Different Distributions', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.legend(fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个示例绘制了三种不同分布的CDF,并添加了清晰的图例。

17. 使用颜色映射绘制CDF

使用颜色映射可以为CDF图添加额外的维度:

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

data = np.random.normal(0, 1, 1000)
x, y = calculate_cdf(data)

plt.figure(figsize=(12, 7))
plt.scatter(x, y, c=y, cmap='viridis', s=10)
plt.colorbar(label='Cumulative Probability')
plt.title('CDF with Color Mapping', fontsize=16)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Cumulative Probability', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

这个例子使用颜色映射来表示累积概率,提供了一种视觉上更丰富的表示方法。

18. 绘制二维CDF

对于二维数据,我们可以绘制二维CDF:

from scipy import stats
import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子以确保结果可重现
np.random.seed(42)

x = np.random.normal(0, 1, 1000)
y = np.random.normal(0, 1, 1000)

xmin, xmax = x.min(), x.max()
ymin, ymax = y.min(), y.max()

xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = stats.gaussian_kde(values)
f = np.reshape(kernel(positions).T, xx.shape)

plt.figure(figsize=(12, 7))
plt.imshow(np.rot90(f), cmap='viridis', extent=[xmin, xmax, ymin, ymax])
plt.colorbar(label='Density')
plt.title('2D Cumulative Distribution Function', fontsize=16)
plt.xlabel('X', fontsize=12)
plt.ylabel('Y', fontsize=12)
plt.text(0.5, 0.5, 'how2matplotlib.com', ha='center', va='center', transform=plt.gca().transAxes, alpha=0.2, fontsize=40)
plt.show()

Output:

使用Matplotlib在Python中计算和绘制累积分布函数的全面指南

这个示例创建了一个二维CDF的热图表示。

总结

本文详细介绍了如何使用Python的Matplotlib库计算和绘制累积分布函数。我们从基本概念开始,逐步深入到更复杂的应用,包括美化图表、比较多个分布、添加置信区间、使用对数刻度等。通过这些示例,读者应该能够掌握使用Matplotlib绘制CDF的各种技巧,并能够根据具体需求定制自己的CDF图表。

CDF是数据分析和可视化中的重要工具,它可以帮助我们更好地理解数据的分布特征。通过本文提供的示例,读者可以将这些技术应用到自己的数据分析项目中,创建信息丰富、视觉吸引力强的CDF图表。

记住,在实际应用中,选择合适的可视化方法取决于数据的性质和你想要传达的信息。CDF图表是一种强大的工具,但它并不是唯一的选择。根据具体情况,你可能还需要考虑其他类型的图表,如直方图、箱线图或核密度估计图等。

最后,持续练习和实验是提高数据可视化技能的关键。尝试将本文中的技术应用到你自己的数据集上,并探索Matplotlib提供的其他功能,以创建更加丰富和有洞察力的可视化效果。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程