You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原始数据在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:16:14