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绘图,具体步骤如下:
解决方案:用生存分析包处理删失数据
- 给数据添加删失标记:用
status字段区分事件发生(1)和右删失(0)的观测 - 用
survival包计算考虑删失的生存函数,再转换为累积分布(1 - 生存概率) - 用
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
相关产品推荐
相关产品推荐

