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

ggplot2的stat_ecdf如何处理右删失数据,使累积分布不趋近于1?

处理右删失数据时,ggplot2 stat_ecdf无法生成不趋近于1的累积分布曲线?

我用ggplot2的stat_ecdf绘制事件发生时间的累积分布,但部分事件存在右删失(尚未发生),希望累积分布曲线不趋近于1。根据官方文档,stat_ecdf的na.rm选项基本无效,请问必须自行编写ECDF函数吗?

最小可复现示例(MWE)

问题在于stat_ecdf没有将NA视为删失数据的选项,无论是否调整x轴范围(这完全不合理),分布曲线始终会趋近于1。

library('ggplot2')
set.seed(0)
x = rbinom(8,20,.5) # 完整真实数据
# x[x>10] = NA # 将NA作为删失处理——问题依旧
g = ggplot(data.frame(x=x),aes(x=x)) +
  stat_ecdf(na.rm=TRUE) + # na.rm参数无效
  lims(x=c(0,10)) # 用xlim模拟删失——CDF被重新缩放至可见数据!?
  # lims(x=c(0,20)) # 无删失情况——结果正确
print(g)

不需要完全自行编写ECDF函数,stat_ecdf本身确实不支持处理删失数据,它默认计算的是完整样本的经验累积分布,必然会强制趋近于1。你可以借助生存分析工具来处理删失数据,再用ggplot绘图,具体步骤如下:

解决方案:用生存分析包处理删失数据

  1. 给数据添加删失标记:用status字段区分事件发生(1)和右删失(0)的观测
  2. 用survival包计算考虑删失的生存函数,再转换为累积分布(1 - 生存概率)
  3. 用geom_step绘制累积分布曲线,曲线最终会停留在「已发生事件数/总样本数」的位置,不会趋近于1

修改后的代码示例:

library(ggplot2)
library(survival)

set.seed(0)
x <- rbinom(8, 20, .5)
# 构造带删失标记的数据:x>10的视为右删失
df <- data.frame(
  time = x,
  status = ifelse(x <= 10, 1, 0) # 1=事件发生,0=右删失
)

# 计算考虑删失的生存函数,转换为累积分布
surv_fit <- survfit(Surv(time, status) ~ 1, data = df)
ecdf_data <- data.frame(
  time = surv_fit$time,
  cum_prob = 1 - surv_fit$surv
)

# 绘制符合需求的累积分布曲线
ggplot(ecdf_data, aes(x = time, y = cum_prob)) +
  geom_step() +
  lims(x = c(0, 10), y = c(0, 1)) +
  labs(x = "事件发生时间", y = "累积分布概率")

手动计算带删失的ECDF(可选)

如果不想依赖survival包,也可以手动计算:

  • 将所有观测(含删失)按时间排序
  • 遍历每个时间点,累计已发生的事件数,除以总样本数得到累积概率
  • 删失观测仅参与排序,不增加事件计数

这种方法需要自己处理排序和计数逻辑,不如用专业包简洁可靠,但灵活性更高。

内容的提问来源于stack exchange,提问作者jessexknight

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 22:24:28