如何基于geom_density()密度曲线计算指定区间的近似观测计数
实现方法
核密度曲线的纵轴是概率密度值,我们只需要计算指定区间内密度曲线的下面积(即该区间的概率),再乘以总观测数,就能得到对应的近似计数,和geom_density输出的平滑结果完全匹配。
完整实现步骤
- 步骤1:计算和
geom_density默认参数一致的核密度结果
# 先构造你提供的tmp序列 tmp <- c(round(seq(0, 12000, ((12000 - 0) / round(1500 * .05)))), round(seq(12000, 18900, ((18900 - 12000) / round(1500 * .1)))), round(seq(18900, 23300, ((23300 - 18900) / round(1500 * .1)))), round(seq(23300, 28100, ((28100 - 23300) / round(1500 * .1)))), round(seq(28100, 33500, ((33500 - 28100) / round(1500 * .1)))), round(seq(33500, 40000, ((40000 - 33500) / round(1500 * .1)))), round(seq(40000, 47700, ((47700 - 40000) / round(1500 * .1)))), round(seq(47700, 56500, ((56500 - 47700) / round(1500 * .1)))), round(seq(56500, 68300, ((68300 - 56500) / round(1500 * .1)))), round(seq(68300, 94200, ((94200 - 68300) / round(1500 * .1)))), round(seq(94200, 200000, ((200000 - 94200) / round(1500 * .05))))) # 核密度计算,参数和ggplot2 geom_density默认参数完全一致(高斯核、nrd0带宽) dens <- density(tmp) total_n <- length(tmp) # 总观测数
- 步骤2:封装区间计数计算函数
用梯形法做数值积分算区间面积,再转换为计数:
count_from_density <- function(lower_bound, upper_bound, dens_obj, total_count) { x_val <- dens_obj$x y_val <- dens_obj$y # 筛选落在目标区间的密度点 range_idx <- x_val >= lower_bound & x_val <= upper_bound # 梯形法计算积分(区间概率) interval_prob <- sum(diff(x_val[range_idx]) * (head(y_val[range_idx], -1) + tail(y_val[range_idx], -1)) / 2) # 概率乘总样本数得到近似计数 return(round(interval_prob * total_count)) }
- 步骤3:测试你举的10050~10100区间示例
# 基于密度曲线的近似计数 est_count <- count_from_density(10050, 10100, dens, total_n) print(est_count) # 可以和原始实际计数对比验证 actual_count <- sum(tmp >= 10050 & tmp <= 10100) print(actual_count)
特殊场景说明
如果你自定义过
geom_density的带宽(bw参数)、核函数(kernel参数),只需要在调用density()时传入相同的参数,就能保证和你画的密度曲线完全匹配。如果要直接从已绘制的ggplot对象提取密度数据,可以用以下方法:
library(ggplot2) # 假设你已经画好了密度图存在p对象里 p <- ggplot(data.frame(val = tmp), aes(x = val)) + geom_density() # 提取图层里的密度数据 plot_data <- ggplot_build(p) dens_from_plot <- data.frame( x = plot_data$data[[1]]$x, y = plot_data$data[[1]]$y ) # 后续积分计算逻辑和上面完全一致
内容的提问来源于stack exchange,提问作者Rene
相关产品推荐
相关产品推荐

