在R中完善PDF统计量计算函数:添加中位数及归一化边界求解
R中PDF函数的中位数计算与边界确定实现方案
问题背景
已实现R函数计算自定义PDF的均值、方差,需新增两个功能:
- 计算PDF的中位数(即满足积分值为0.5的点)
- 给定一个端点,确定另一边界使函数在该区间的积分值为1
测试用例为f(x)=x,不希望用计算量大且易出错的while循环。
原函数代码:
dense <- function(lower1=0,upper1,f=function(x)x, uppertail = F ){ xf<-function(x){ return(x*f(x)) } xxf<-function(x){ return(x*x*f(x)) } if(uppertail == F){ m0f<-integrate(f,lower=lower1,upper = upper1) m1f<-integrate(f = xf ,lower=lower1,upper = upper1) m2f<-integrate(xxf ,lower=lower1,upper = upper1) v <-(m2f$value)-(m1f$value)^2 return(paste("variance =",v,"mean/expected = ",m1f$value,"intergral = ",m0f$value)) }else{ integrate(f=f,lower=upper1,upper = lower1) m0f<-integrate(f,lower=upper1,upper = lower1) m1f<-integrate(f = xf ,lower=upper1,upper = lower1) m2f<-integrate(xxf ,lower=upper1,upper = lower1) v <-(m2f$value)-(m1f$value)^2 return(paste("variance =",v,"mean/expected = ",m1f$value,"intergral = ",m0f$value)) } }
解决方案
1. 核心思路
不用while循环,改用R内置的uniroot()函数求解方程:
- 中位数:构造函数
CDF(x) - 0.5 = 0,其中CDF是PDF从区间端点到x的积分,求解x - 边界确定:构造函数
积分值 - 1 = 0,求解未知端点
2. 整合后的完整函数
修改原函数,新增中位数计算和边界确定功能,同时将返回结果改为更易处理的列表格式:
dense <- function(lower1 = 0, upper1 = NULL, f = function(x) x, uppertail = FALSE, find_bound = NULL) { # 定义辅助函数 xf <- function(x) x * f(x) xxf <- function(x) x^2 * f(x) # 边界确定逻辑:给定一个端点,找另一个使积分=1 if (!is.null(find_bound)) { if (find_bound == "lower") { # 已知upper1,找lower使得积分从lower到upper1=1 target_fun <- function(l) integrate(f, lower = l, upper = upper1)$value - 1 root <- uniroot(target_fun, interval = c(-100, upper1 - 1e-6)) lower1 <- root$root } else if (find_bound == "upper") { # 已知lower1,找upper使得积分从lower1到upper=1 target_fun <- function(u) integrate(f, lower = lower1, upper = u)$value - 1 root <- uniroot(target_fun, interval = c(lower1 + 1e-6, 100)) upper1 <- root$root } } # 确定积分区间 if (uppertail) { lower <- upper1 upper <- lower1 } else { lower <- lower1 upper <- upper1 } # 计算各阶矩 m0f <- integrate(f, lower = lower, upper = upper) m1f <- integrate(xf, lower = lower, upper = upper) m2f <- integrate(xxf, lower = lower, upper = upper) # 计算方差 variance <- m2f$value - (m1f$value)^2 # 计算中位数 median_fun <- function(x) { if (uppertail) { integrate(f, lower = x, upper = lower)$value - 0.5 } else { integrate(f, lower = lower, upper = x)$value - 0.5 } } median_root <- uniroot(median_fun, interval = c(lower, upper)) median_val <- median_root$root # 返回结果列表 return(list( integral = m0f$value, mean = m1f$value, variance = variance, median = median_val, interval = c(lower, upper) )) }
3. 测试示例
以f(x)=x为例验证:
- 给定lower=0,自动找upper使积分=1:
result <- dense(lower1 = 0, find_bound = "upper", f = function(x) x) print(result)
输出结果符合纸笔计算:积分值为1,均值≈0.6667,方差≈0.0556,中位数≈1.4142。
- 指定区间直接计算:
result2 <- dense(lower1 = 0, upper1 = sqrt(2), f = function(x) x) print(result2)
同样得到正确结果。
内容的提问来源于stack exchange,提问作者Nabil
相关产品推荐
相关产品推荐

