
R Under development (unstable) (2022-08-09 r82699) -- "Unsuffered Consequences"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

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.

> library(survival)
> options(na.action=na.exclude)
> aeq <- function(x,y,...)  all.equal(as.vector(x), as.vector(y), ...)
> 
> #  Make sure strata is retained, and that the overall variance is correct
> fit1 <- coxph(Surv(time, status) ~ age + offset(ph.ecog*0) +strata(sex), lung)
> fit2 <- coxph(Surv(time, status) ~ age + ph.ecog +strata(sex), lung)
> 
> test <- concordance(fit1, fit2, influence=1)
> 
> ksex <- model.frame(fit1)[["strata(sex)"]]
> test1 <- concordance(fit1$y ~ fit1$linear.predictors + strata(ksex), 
+                      reverse=TRUE, influence=1)
> test2 <- concordance(fit1$y ~ fit2$linear.predictors + strata(ksex), 
+                      reverse=TRUE, influence=1)
> aeq(test$concordance, c(test1$concordance, test2$concordance))
[1] TRUE
> aeq(diag(test$var), c(test1$var[1], test2$var[1]))
[1] TRUE
> aeq(test$dfbeta, cbind(test1$dfbeta, test2$dfbeta))
[1] TRUE
> 
> cvec <- c(-1, 1)
> aeq(cvec %*% test$var %*% cvec, sum((test1$dfbeta - test2$dfbeta)^2))
[1] TRUE
> 
> # Time weights
> # Start with a very small data set: aml has 23 subjects
> #
> atest1 <- concordance(Surv(time, status) ~ x, aml, ranks=TRUE)
> atest2 <- concordance(Surv(time, status) ~ x, aml, ranks=TRUE, timewt='S')
> atest3 <- concordance(Surv(time, status) ~ x, aml, ranks=TRUE, timewt='S/G')
> atest4 <- concordance(Surv(time, status) ~ x, aml, ranks=TRUE, timewt='n/G2')
> # The ranks data frame agrees for all but weights
> all.equal(atest1$ranks[, -3], atest2$ranks[, -3])
[1] TRUE
> all.equal(atest1$ranks[, -3], atest3$ranks[, -3])
[1] TRUE
> all.equal(atest1$ranks[, -3], atest4$ranks[, -3])
[1] TRUE
> 
> wt1 <- cbind(atest1$ranks[,"timewt"], atest2$ranks[,"timewt"],
+              atest3$ranks[,"timewt"], atest4$ranks[,"timewt"])
>             
> # survfit0 adds time 0 to the curves
> # to break ties between censor/death for G, we need to add an offset to
> #  the censoring times.  Since time is integer, .1 works nicely
> s1 <- survfit0(survfit(Surv(time, status) ~ 1, aml))
> g1 <- survfit0(survfit(Surv(time + .1*(1-status), 1-status) ~1, aml))
> 
> # The ingredients of the weights
> indx <- match(atest1$ranks[,"time"], s1$time)
> nrisk  <- s1$n.risk[indx]
> sminus <- s1$surv[indx-1]
> gminus <- g1$surv[findInterval(atest1$ranks[,"time"], g1$time)]
> n <- nrow(aml)
> 
> wt2 <- cbind(nrisk, n*sminus, n*sminus/gminus, nrisk/gminus^2)
> aeq(wt1, wt2)
[1] TRUE
> 
> # The sum of weighted ranks should equal (C-D) for a Cox model fit
> tfun <- function(cfit, reverse=FALSE) {
+     t1 <- sum(cfit$ranks$timewt * cfit$ranks$rank)
+     t2 <- cfit$count[1] - cfit$count[2]
+     all.equal(unname(t1), unname(t2))
+ }
> tfun(atest1)
[1] TRUE
> tfun(atest2)
[1] TRUE
> tfun(atest3)
[1] TRUE
> tfun(atest4)
[1] TRUE
> 
> # The nafld data set has strong and early censoring (one of the only ones
> # in the package that does.) So it is a good check of time weights.
> #
> nfit <- coxph(Surv(futime, status) ~ male + pspline(age), nafld1)
> cn1 <- concordance(nfit, timewt='n', ranks=TRUE)
> cn2 <- concordance(nfit, timewt='S', ranks=TRUE)
> cn3 <- concordance(nfit, timewt='S/G', ranks=TRUE)
> cn4 <- concordance(nfit, timewt='n/G2', ranks=TRUE)
> 
> sfit <- survfit0(survfit(Surv(futime, status) ~ 1, nafld1))
> gfit <- survfit0(survfit(Surv(futime + .1*(status==0), 1-status) ~0, nafld1))
> 
> # The ingredients of the weights
> dtime <- cn1$ranks[, "time"]
> indx <- match(dtime, sfit$time)
> nrisk  <- sfit$n.risk[indx]
> sminus <- sfit$surv[indx-1]
> gminus <- gfit$surv[findInterval(dtime, gfit$time)]
> n <- nrow(nafld1)
> 
> wt1 <- cbind(cn1$ranks[, "timewt"], cn2$ranks[,"timewt"],
+              cn3$ranks[, "timewt"], cn4$ranks[,"timewt"])
> wt2 <- cbind(nrisk, n*sminus, n*sminus/gminus, nrisk/gminus^2)
> aeq(wt1, wt2)
[1] TRUE
> 
> rd1 <- cn1$ranks
> rd2 <- cn2$ranks
> rd3 <- cn3$ranks
> all.equal(rd1[c('time', 'rank', 'casewt')], rd2[c('time', 'rank', 'casewt')])
[1] TRUE
> all.equal(rd1[c('time', 'rank', 'casewt')], rd3[c('time', 'rank', 'casewt')])
[1] TRUE
> 
> tfun(cn1)
[1] TRUE
> tfun(cn2)
[1] TRUE
> tfun(cn3)
[1] TRUE
> tfun(cn4)
[1] TRUE
> 
> 
> proc.time()
   user  system elapsed 
  1.628   0.068   1.726 
