如何用原始数据在R的ggplot中绘制双样本Kolmogorov-Smirnov图
用ggplot基于原始数据绘制双样本Kolmogorov-Smirnov图
我想复现双样本Kolmogorov-Smirnov图,之前看到的示例用rnorm生成模拟数据,但我想用自己的原始数据实现(优先用ggplot)。我尝试用ecdf和自定义函数构建变量但没成功,怀疑是重复值或样本量小导致的。
我的数据
dry_2006 <- structure(list(CYR = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), levels = c("2006", "2015", "2016", "2018"), class = "factor"), Month = c(3, 3, 2, 3, 3, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 2, 3, 2, 3, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 3, 3), temp = c(18.66, 21.36, 25.03, 21.58, 19.24, 19.32, 23.6, 25.57, 21.95, 24.9, 19.48, 25.82, 25.15, 23.04, 24.18, 22.85, 19.79, 25.72, 25.29, 23.82, 23.9, 23.37, 20.55, 26.04, 25.88, 24.51, 24.02, 21, 23.79, 27.16, 26.97, 24.93, 24.17, 23.66, 22.13, 28.06, 27.37, 25.89, 28.09, 26.83, 25.52, 28.3, 26.58, 28.94, 26.3, 26.48, 24.46)), class = "data.frame", row.names = c(NA, -47L))
解决方案
针对你的数据,我们可以基于2月和3月的温度数据绘制双样本KS图,步骤如下:
1. 拆分样本并计算ECDF
library(ggplot2) # 从数据中拆分两个对比样本:2月和3月的温度 sample_feb <- dry_2006$temp[dry_2006$Month == 2] sample_mar <- dry_2006$temp[dry_2006$Month == 3] # 计算两个样本的经验累积分布函数 ecdf_feb <- ecdf(sample_feb) ecdf_mar <- ecdf(sample_mar) # 整理所有唯一温度值,用于生成连续的ECDF曲线数据 all_temp <- sort(unique(c(sample_feb, sample_mar))) ecdf_data <- data.frame( temp = all_temp, feb_ecdf = ecdf_feb(all_temp), mar_ecdf = ecdf_mar(all_temp) )
2. 计算KS统计量及最大差值位置
# 执行KS检验 ks_result <- ks.test(sample_feb, sample_mar) max_diff <- ks_result$statistic # 找到两条ECDF曲线差值最大的位置 diff_values <- abs(ecdf_data$feb_ecdf - ecdf_data$mar_ecdf) max_pos_idx <- which.max(diff_values) max_temp <- ecdf_data$temp[max_pos_idx] max_feb_ecdf <- ecdf_data$feb_ecdf[max_pos_idx] max_mar_ecdf <- ecdf_data$mar_ecdf[max_pos_idx]
3. 用ggplot绘制KS图
ggplot(ecdf_data, aes(x = temp)) + # 绘制两条ECDF阶梯曲线 geom_step(aes(y = feb_ecdf, color = "2月"), size = 1) + geom_step(aes(y = mar_ecdf, color = "3月"), size = 1) + # 标注KS最大差值的虚线 geom_segment( aes( x = max_temp, xend = max_temp, y = min(max_feb_ecdf, max_mar_ecdf), yend = max(max_feb_ecdf, max_mar_ecdf) ), color = "red", linetype = "dashed", size = 1 ) + # 添加KS统计量文本标注 annotate( "text", x = max_temp, y = (max_feb_ecdf + max_mar_ecdf)/2, label = paste("KS统计量 =", round(max_diff, 3)), color = "red", vjust = -0.5 ) + # 图表样式设置 labs(x = "温度(℃)", y = "累积概率", color = "月份") + theme_minimal() + theme(legend.position = "top")
关键说明
geom_step是绘制ECDF的标准方法,天然支持重复值(重复数据会让阶梯上升幅度更大),小样本量也能正常生成曲线- 自动计算并标注KS检验的核心统计量,直观展示两个分布的最大差异点
内容的提问来源于stack exchange,提问作者Nate
相关产品推荐
相关产品推荐

