news 2026/4/30 13:11:23

别再傻傻分不清了!用Python和R语言代码实例,5分钟搞懂PDF和CDF的区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再傻傻分不清了!用Python和R语言代码实例,5分钟搞懂PDF和CDF的区别

别再傻傻分不清了!用Python和R语言代码实例,5分钟搞懂PDF和CDF的区别

第一次接触概率密度函数(PDF)和累积分布函数(CDF)时,很多人都会被这两个看似相似实则完全不同的概念搞得晕头转向。作为一名经常需要处理数据分布问题的分析师,我完全理解这种困惑——毕竟教科书上那些晦涩的数学定义和积分符号,确实不如几行代码和直观的图表来得直接有效。

今天我们就用Python和R这两种最流行的数据分析语言,通过实际代码和可视化图形,帮你彻底理清PDF和CDF的区别与联系。无论你是机器学习初学者还是需要快速回顾的数据分析师,这篇文章提供的代码片段都能直接复制使用,让你在实践中真正掌握这两个核心概念。

1. 基础概念速览:从生活实例理解PDF与CDF

在深入代码之前,我们先花一分钟建立直观理解。想象你正在测量一群人的身高:

  • PDF回答的问题是:"身高正好是170cm的概率有多大?"对于连续变量,这个概率实际上是0(因为可能是170.0001cm或169.9999cm),所以PDF值表示的是概率密度而非具体概率
  • CDF回答的问题是:"身高不超过170cm的概率有多大?"这个概率是有实际意义的,比如可能是0.3(即30%的人不超过170cm)

关键区别记忆法

  • PDF是"点"的概率密度(像显微镜看一个点)
  • CDF是"累积"到某点的概率(像从最矮累计到某个高度)

小技巧:在离散分布(如骰子)中,PDF可以直接表示具体值的概率,而连续分布中PDF需要积分才能得到概率。

2. Python实战:用Matplotlib可视化正态分布的PDF与CDF

让我们用Python中最常用的数据可视化库Matplotlib,绘制标准正态分布(均值为0,标准差为1)的PDF和CDF曲线。

2.1 环境准备与数据生成

首先安装必要的库(如果尚未安装):

pip install numpy matplotlib scipy

然后生成标准正态分布的数据点:

import numpy as np from scipy.stats import norm import matplotlib.pyplot as plt # 生成-4到4之间等间距的1000个点 x = np.linspace(-4, 4, 1000) # 计算每个点的PDF和CDF值 pdf = norm.pdf(x) # 标准正态分布的PDF cdf = norm.cdf(x) # 标准正态分布的CDF

2.2 绘制对比图形

现在让我们把PDF和CDF画在同一坐标系中,方便对比:

plt.figure(figsize=(12, 5)) # 绘制PDF曲线 plt.subplot(1, 2, 1) plt.plot(x, pdf, 'b-', lw=2, label='PDF') plt.fill_between(x, pdf, alpha=0.2) plt.title('标准正态分布的概率密度函数(PDF)') plt.xlabel('值') plt.ylabel('概率密度') plt.legend() # 绘制CDF曲线 plt.subplot(1, 2, 2) plt.plot(x, cdf, 'r-', lw=2, label='CDF') plt.title('标准正态分布的累积分布函数(CDF)') plt.xlabel('值') plt.ylabel('累积概率') plt.legend() plt.tight_layout() plt.show()

运行结果解读

  • 左图PDF呈钟形曲线,最高点在均值0处
  • 右图CDF是单调递增的S型曲线,从0增长到1
  • PDF曲线下的总面积等于1,对应CDF最终达到1

2.3 关键关系演示:PDF是CDF的导数

数学上,PDF是CDF的导数。让我们用数值计算验证这一点:

# 计算CDF的数值导数 cdf_derivative = np.gradient(cdf, x) # 对比PDF和CDF的导数 plt.figure(figsize=(8, 5)) plt.plot(x, pdf, 'b-', lw=2, label='PDF') plt.plot(x, cdf_derivative, 'r--', lw=2, label='CDF的数值导数') plt.title('PDF与CDF导数的关系验证') plt.legend() plt.show()

你会看到两条曲线几乎完全重合,直观验证了"PDF是CDF的导数"这一重要关系。

3. R语言实现:用ggplot2绘制指数分布的PDF与CDF

对于习惯使用R语言的分析师,我们再用ggplot2展示指数分布的PDF和CDF。指数分布常用于建模等待时间,其PDF和CDF有更明显的不对称特性。

3.1 准备数据

首先安装并加载必要的包:

install.packages("ggplot2") # 如果尚未安装 library(ggplot2)

生成指数分布的数据:

# 设置参数λ=0.5 lambda <- 0.5 x <- seq(0, 10, length.out=1000) # 计算PDF和CDF pdf <- dexp(x, rate=lambda) cdf <- pexp(x, rate=lambda) # 创建数据框 df <- data.frame(x, pdf, cdf)

3.2 绘制精美对比图

使用ggplot2的分面(facet)功能并排显示:

library(tidyr) # 转换数据为长格式 df_long <- gather(df, key="function_type", value="value", -x) # 绘制图形 ggplot(df_long, aes(x=x, y=value, color=function_type)) + geom_line(size=1) + facet_wrap(~function_type, scales="free_y", labeller=as_labeller(c(pdf="PDF (λ=0.5)", cdf="CDF (λ=0.5)"))) + labs(title="指数分布的PDF与CDF对比", x="值", y="") + theme_minimal() + theme(legend.position="none")

图形特征观察

  • PDF从λ值开始快速下降,右偏明显
  • CDF逐渐趋近于1,曲线上升速度与PDF对应
  • 当x=2时(即1/λ),CDF约为0.632(1-1/e)

3.3 计算特定概率的实际案例

假设我们建模客户到达间隔时间(单位:分钟),λ=0.5表示平均每分钟到达0.5个客户:

# 计算1分钟内没有客户到达的概率 no_customer_in_1min <- 1 - pexp(1, rate=0.5) print(paste("1分钟内无客户到达的概率:", round(no_customer_in_1min, 4))) # 计算3分钟内至少一个客户到达的概率 at_least_one_in_3min <- pexp(3, rate=0.5) print(paste("3分钟内至少一个客户到达的概率:", round(at_least_one_in_3min, 4)))

这种实际问题的计算展示了CDF的直接应用价值。

4. 高级应用:自定义分布与非参数估计

在实际数据分析中,我们经常需要处理非标准分布。这时可以使用核密度估计(KDE)来估计PDF,并用经验分布函数估计CDF。

4.1 Python实现经验分布

给定一组样本数据,我们可以这样估计CDF:

from statsmodels.distributions.empirical_distribution import ECDF # 生成随机样本 np.random.seed(42) samples = np.random.normal(0, 1, 1000) # 计算经验CDF ecdf = ECDF(samples) # 绘制图形 plt.figure(figsize=(8, 5)) plt.step(ecdf.x, ecdf.y, where='post', label='经验CDF') plt.plot(x, cdf, 'r--', label='理论CDF') plt.title('经验CDF与理论CDF对比') plt.legend() plt.show()

4.2 R语言实现核密度估计

在R中,使用density()函数可以轻松获得PDF的核密度估计:

# 生成随机样本 set.seed(123) samples <- rnorm(1000) # 核密度估计 kde <- density(samples) # 绘制对比图 plot(kde, main="核密度估计(PDF)", lwd=2) curve(dnorm(x), add=TRUE, col="red", lty=2, lwd=2) legend("topright", legend=c("KDE估计", "真实PDF"), col=c("black", "red"), lty=1:2)

4.3 实际数据案例:收入分布分析

假设我们有一组收入数据(单位:万元):

incomes = np.array([15, 22, 18, 35, 12, 28, ..., 42]) # 实际数据会更长 # 计算PDF和CDF kde = gaussian_kde(incomes) x_vals = np.linspace(min(incomes), max(incomes), 1000) pdf_vals = kde(x_vals) cdf_vals = np.array([np.mean(incomes <= x) for x in x_vals]) # 绘制双轴图 fig, ax1 = plt.subplots(figsize=(10, 6)) ax1.plot(x_vals, pdf_vals, 'b-', label='PDF (核密度估计)') ax1.set_xlabel('收入(万元)') ax1.set_ylabel('概率密度', color='b') ax2 = ax1.twinx() ax2.plot(x_vals, cdf_vals, 'r-', label='CDF (经验分布)') ax2.set_ylabel('累积概率', color='r') plt.title('收入分布的PDF与CDF') plt.show()

这种分析可以帮助我们回答诸如"收入低于20万的比例是多少"或"前10%的收入门槛是多少"等实际问题。

5. 常见误区与实用技巧

在长期使用PDF和CDF的过程中,我总结了一些容易混淆的地方和实用技巧:

5.1 必须避免的三个常见错误

  1. 混淆纵坐标含义

    • PDF的纵轴是"密度"不是概率
    • CDF的纵轴是概率(0到1之间)
  2. 错误理解PDF值

    • 对于连续变量,PDF在某点的值不是概率
    • 只有对区间积分才能得到概率
  3. 忽视分布类型差异

    • 离散分布的PDF可以有非零概率点
    • 连续分布的PDF需要区间才有非零概率

5.2 实用代码片段收藏

Python快速查询表

from scipy import stats # 正态分布查询 def normal_probability(mu, sigma, lower, upper): """ 计算正态分布在[lower, upper]区间内的概率 """ return stats.norm.cdf(upper, mu, sigma) - stats.norm.cdf(lower, mu, sigma) # 示例:标准正态分布在[-1,1]的概率 print(normal_probability(0, 1, -1, 1)) # 约0.6826

R语言快速查询

# 快速计算分位数 quantile_info <- function(distribution, p) { q <- quantile(distribution, probs=p) cat(sprintf("第%.0f百分位数: %.2f\n", p*100, q)) } # 示例:找出收入分布的中位数 quantile_info(incomes, 0.5)

5.3 可视化进阶技巧

Python动态交互可视化

from ipywidgets import interact def plot_distribution(mean=0, std=1): x = np.linspace(mean-4*std, mean+4*std, 1000) pdf = norm.pdf(x, mean, std) cdf = norm.cdf(x, mean, std) plt.figure(figsize=(10, 4)) plt.subplot(1, 2, 1) plt.plot(x, pdf) plt.title(f'PDF (μ={mean}, σ={std})') plt.subplot(1, 2, 2) plt.plot(x, cdf) plt.title(f'CDF (μ={mean}, σ={std})') plt.tight_layout() plt.show() interact(plot_distribution, mean=(-2, 2, 0.1), std=(0.1, 2, 0.1))

R Shiny交互应用

library(shiny) ui <- fluidPage( sliderInput("lambda", "λ参数:", min=0.1, max=2, value=0.5, step=0.1), plotOutput("distPlot") ) server <- function(input, output) { output$distPlot <- renderPlot({ x <- seq(0, 10, length.out=1000) pdf <- dexp(x, rate=input$lambda) cdf <- pexp(x, rate=input$lambda) par(mfrow=c(1, 2)) plot(x, pdf, type="l", main=paste("PDF (λ=", input$lambda, ")")) plot(x, cdf, type="l", main=paste("CDF (λ=", input$lambda, ")")) }) } shinyApp(ui, server)

掌握这些代码后,你可以轻松应对各种分布分析需求,无论是学术研究还是商业分析场景。记住,理解PDF和CDF的最好方式就是多动手实践——尝试修改代码中的参数,观察图形变化,很快你就能培养出对概率分布的直观感觉。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 13:09:41

打卡信奥刷题(3190)用C++实现信奥题 P8085 [COCI 2011/2012 #4] KRIPTOGRAM

P8085 [COCI 2011/2012 #4] KRIPTOGRAM 题目描述 现有一段明文和一部分密文。明文和密文都由英文单词组成&#xff0c;且密文中的一个单词必然对应着明文中的一个单词。 求给出的密文在明文中可能出现的最早位置。 输入格式 第一行&#xff0c;若干个英文单词和一个 $&…

作者头像 李华
网站建设 2026/4/30 13:06:50

网信办查处剪映:AI生成内容,标识是底线!

4月28日&#xff0c;国家互联网信息办公室指导属地网信部门&#xff0c;依法查处了“剪映”&#xff0c;“猫箱”App&#xff0c;以及“即梦AI”网站&#xff0c;核心原因是这些平台未有效落实人工智能生成合成内容标识规定&#xff0c;违反了《网络安全法》等相关法律规定。 一…

作者头像 李华
网站建设 2026/4/30 13:06:24

真我GT Neo闪速版UI4.0保姆级教程:用KernelSU隐藏Root,搞定银行和交管12123

真我GT Neo闪速版深度Root隐藏方案&#xff1a;从KernelSU内核到金融级应用完美运行指南 对于Realme GT Neo闪速版用户而言&#xff0c;系统深度定制与金融类应用的严格检测始终是Root路上的双重阻碍。本文将以UI4.0系统为基准&#xff0c;通过KernelSU的革新架构配合模块化方案…

作者头像 李华
网站建设 2026/4/30 13:05:04

轻量级LLM推理引擎nano-vLLM:Python实现的高效推理方案

1. 轻量级LLM推理引擎的崛起 在大型语言模型&#xff08;LLM&#xff09;应用爆发的今天&#xff0c;推理效率成为制约实际落地的关键瓶颈。传统方案如vLLM虽然性能强劲&#xff0c;但其复杂的C/CUDA架构和庞大的代码库&#xff08;超过10万行&#xff09;让普通开发者难以理解…

作者头像 李华