1D核密度估计PDF比值:如何设置尾部边界?
解决R中核密度估计在指定端点强制为0的问题
你的问题本质是:默认的核密度估计(比如stats包的density()用的高斯核)是无界的,即使你设置了from和to,核函数依然会覆盖到边界外的区域,导致端点处密度不为0。结合你的需求(4周和16周无观测,后续要计算PDF比值和置换检验),有两种可靠的解决方法:
方法1:用ks包做有界核密度估计(统计上更严谨)
如果你的数据取值范围明确是(4,16)(不可能出现4周前或16周后的观测),用专门的有界核密度工具更合适。ks包的kde()函数支持设置边界约束,自动让边界外的密度为0,同时保证边界内的密度积分严格为1,不用手动调整。
代码示例:
# 先安装并加载ks包 install.packages("ks") library(ks) # 定义统一的x轴 common_x = seq(4, 16, by=0.02) # 估计对照组的有界核密度,指定xmin=4、xmax=16 kde_ctrl = kde(x = control$week, xmin = 4, xmax = 16, h = 0.7) # 把密度值插值到你的common_x上 pdf_ctrl = approx(kde_ctrl$eval.points[[1]], kde_ctrl$estimate, xout = common_x) # 处理组做同样的操作 kde_treat1 = kde(x = treatment1$week, xmin = 4, xmax = 16, h = 0.7) pdf1 = approx(kde_treat1$eval.points[[1]], kde_treat1$estimate, xout = common_x) # 现在pdf_ctrl$y和pdf1$y在x=4、x=16处都是0,且整个区间内的密度积分是1
方法2:手动截断+归一化(用基础stats包实现)
如果不想额外安装包,可以手动截断默认核密度的结果,但必须重新归一化——直接把端点设为0会破坏密度的归一性(积分不再是1),后续计算比值会出错。
代码示例:
common_x = seq(4, 16, by=0.02) # 先估计密度,范围稍微超出4和16,方便后续截断 pdf_ctrl_raw = density(control$week, bw=0.7, from=3.8, to=16.2, n=1000) x_raw = pdf_ctrl_raw$x y_raw = pdf_ctrl_raw$y # 把x≤4或x≥16的密度值强制设为0 y_truncated = ifelse(x_raw <= 4 | x_raw >= 16, 0, y_raw) # 用梯形法计算截断后的密度积分,用来做归一化 integral = sum(diff(x_raw) * (head(y_truncated, -1) + tail(y_truncated, -1)) / 2) # 重新缩放密度,让[4,16]内的积分等于1 y_normalized = y_truncated / integral # 插值到你的common_x上 pdf_ctrl = approx(x_raw, y_normalized, xout=common_x) # 处理组重复相同步骤 pdf1_raw = density(treatment1$week, bw=0.7, from=3.8, to=16.2, n=1000) x1_raw = pdf1_raw$x y1_raw = pdf1_raw$y y1_truncated = ifelse(x1_raw <=4 | x1_raw >=16, 0, y1_raw) integral1 = sum(diff(x1_raw) * (head(y1_truncated, -1) + tail(y1_truncated, -1))/2) y1_normalized = y1_truncated / integral1 pdf1 = approx(x1_raw, y1_normalized, xout=common_x)
重要提醒
- 不管用哪种方法,归一化都是必须的:核密度是概率密度函数,要求整个取值区间内的积分等于1,否则后续的PDF比值、置换检验结果都会失真。
- 做置换检验时,每个置换样本的密度估计都要遵循完全相同的规则(要么用ks包的有界估计,要么用手动截断归一化),保证统计量的计算一致性。
内容的提问来源于stack exchange,提问作者lmbradley
相关产品推荐
相关产品推荐

