154 lines
5.4 KiB
Plaintext
Raw Permalink Normal View History

2025-01-12 00:52:51 +08:00
R Under development (unstable) (2024-04-29 r86493) -- "Unsuffered Consequences"
Copyright (C) 2024 The R Foundation for Statistical Computing
Platform: aarch64-unknown-linux-gnu
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> #
> # Verify that predict(coxfit) agrees with survfit for type= expected and survival
> # This also acts as a check on summary.survfit
> #
> library(survival)
> aeq <- function(x,y, ...) all.equal(as.vector(x), as.vector(y), ...)
>
> fit1 <- coxph(Surv(time, status) ~ age + ph.ecog, lung)
>
> d1 <- data.frame(age= 40 * 1:8*5, ph.ecog= rep(0:2, length=8))
> curves <- survfit(fit1, newdata= d1)
>
> # the status variable isn't used, but has to be there
> d1a <- cbind(time= 1:8 * 60, status=1, d1) # unique time per subject
> d1b <- cbind(time= 365, status=1, d1) # same time for each
>
> p1 <- predict(fit1, newdata= d1a, type="expected", se.fit=TRUE)
> p2 <- predict(fit1, newdata= d1a, type="survival", se.fit=TRUE)
> p3 <- predict(fit1, newdata= d1b, type="survival", se.fit=TRUE)
>
> csum1 <- summary(curves, time= 1:8 * 60)
> aeq(p1$fit, diag(csum1$cumhaz))
[1] TRUE
> aeq(p1$se.fit , diag(csum1$std.chaz))
[1] TRUE
> aeq(p2$fit, diag(csum1$surv))
[1] TRUE
> aeq(p2$se.fit, diag(csum1$std.err))
[1] TRUE
>
> csum2 <- summary(curves, time=365)
> aeq(p3$fit,csum2$surv)
[1] TRUE
> aeq(p3$se.fit, csum2$std.err)
[1] TRUE
>
> # Harder, add a strata
> fit2 <- coxph(Surv(time, status) ~ age + ph.ecog + strata(sex), lung)
> d2 <- data.frame(age= 40 + 1:8*5, ph.ecog= rep(0:2, length=8), sex=rep(1:2,4))
> curve2 <- survfit(fit2, newdata= d2[,1:2])
>
> d2a <- cbind(time= 1:8 * 60, status=1, d2) # unique time per subject
> d2b <- cbind(time= 365, status=1, d2) # same time for each
>
> p1 <- predict(fit2, newdata= d2a, type="expected", se.fit=TRUE)
> p2 <- predict(fit2, newdata= d2a, type="survival", se.fit=TRUE)
> p3 <- predict(fit2, newdata= d2b, type="survival", se.fit=TRUE)
>
> csum1 <- summary(curve2, time= 1:8 * 60, data.frame=TRUE)
> dummy <- data.frame(data=1:8, time= 1:8*60, strata=paste0("sex=", rep(1:2,4)))
> temp <- merge(dummy, csum1, all.x=TRUE) # select the correct rows from csum1
> aeq(p1$fit, temp$cumhaz)
[1] TRUE
> aeq(p1$se.fit , temp$std.chaz)
[1] TRUE
> aeq(p2$fit, temp$surv)
[1] TRUE
> aeq(p2$se.fit, temp$std.err)
[1] TRUE
>
> csum2 <- summary(curve2, time=365)
> indx <- cbind(rep(1:2, 4), 1:8)
> aeq(p3$fit,csum2$surv[indx])
[1] TRUE
> aeq(p3$se.fit, csum2$std.err[indx])
[1] TRUE
>
> # Repeat for (time1, time2) data
> fit3 <- coxph(Surv(tstart, tstop, status) ~ age + treat, cgd)
> d3 <- data.frame(age= c(2,12, 20,30, 40),
+ treat = rep(levels(cgd$treat), length=5))
>
> curve3 <- survfit(fit3, newdata=d3)
>
> d3a <- cbind(tstart= c(0, 50, 100, 200, 250),
+ tstop = c(400, 140, 150, 260, 310), status=1, d3)
> d3b <- cbind(tstart=0, tstop=365, status=1, d3)
>
> p4 <- predict(fit3, newdata=d3a, type='expected', se.fit=TRUE)
> p5 <- predict(fit3, newdata=d3b, type='survival', se.fit=TRUE)
> # type survival is only valid from the start of the curve forward, so no d3a
>
> alltime <- sort(unique(c(d3a$tstart, d3a$tstop)))
> csum3 <-summary(curve3, times= alltime)
> temp1 <- csum3$cumhaz[cbind(match(d3a$tstart, alltime), 1:nrow(d3a))]
> temp2 <- csum3$cumhaz[cbind(match(d3a$tstop, alltime), 1:nrow(d3a))]
> aeq(p4$fit, temp2- temp1)
[1] TRUE
>
> temp3 <- csum3$std.chaz[cbind(match(d3a$tstart, alltime), 1:nrow(d3a))]
> temp4 <- csum3$std.chaz[cbind(match(d3a$tstop, alltime), 1:nrow(d3a))]
> aeq(p4$se.fit, sqrt(temp4^2 - temp3^2))
[1] TRUE
>
> csum4 <- summary(curve3, times=365)
> aeq(p5$fit, csum4$surv)
[1] TRUE
> aeq(p5$se.fit, csum4$std.err)
[1] TRUE
>
>
> # Harder case: add a strata to the problem
> fit4 <- coxph(Surv(tstart, tstop, status) ~ age + treat + strata(hos.cat), cgd)
> d4 <- data.frame(age= c(2,12, 20,30, 40),
+ treat = rep(levels(cgd$treat), length=5),
+ hos.cat= levels(cgd$hos.cat)[c(1,2,4,3,2)])
>
> curve4 <- survfit(fit4, newdata=d4)
> # by including hos.cat in the above curve4 has 5 strata, one per subject,
> # and no data dimension
>
> d4a <- cbind(tstart= c(0, 50, 100, 200, 250),
+ tstop = c(400, 140, 150, 260, 310), status=1, d4)
> d4b <- cbind(tstart=0, tstop=365, status=1, d4)
> p4 <- predict(fit4, newdata=d4a, type='expected', se.fit=TRUE)
> p5 <- predict(fit4, newdata=d4b, type='survival', se.fit=TRUE)
>
> # sort() skipped on purpose, summary should handle it
> alltime <- unique(c(d4a$tstart, d4a$tstop))
> csum5 <- summary(curve4, times=alltime, extend=TRUE)
> indx1 <- match(d4a$tstart, csum5$time) + 0:4*length(alltime)
> indx2 <- match(d4a$tstop, csum5$time) + 0:4*length(alltime)
> aeq(p4$fit, csum5$cumhaz[indx2] - csum5$cumhaz[indx1])
[1] TRUE
> aeq(p4$se.fit, sqrt(csum5$std.chaz[indx2]^2 - csum5$std.chaz[indx1]^2))
[1] TRUE
>
> csum6 <- summary(curve4, times= 365, extend=TRUE)
> aeq(p5$fit, csum6$surv)
[1] TRUE
> aeq(p5$se.fit, csum6$std.err)
[1] TRUE
>
> proc.time()
user system elapsed
0.455 0.020 0.473