Rev 4476 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#SCCS @(#)coxph.s 5.12 06/12/00# Version with general penalized likelihoodscoxph <- function(formula=formula(data), data=parent.frame(),weights, subset, na.action, init,control, method= c("efron", "breslow", "exact"),singular.ok =TRUE, robust=FALSE,model=FALSE, x=FALSE, y=TRUE, ...) {method <- match.arg(method)call <- match.call()m <- match.call(expand.dots=FALSE)temp <- c("", "formula", "data", "weights", "subset", "na.action")m <- m[ match(temp, names(m), nomatch=0)]special <- c("strata", "cluster")Terms <- if(missing(data)) terms(formula, special)else terms(formula, special, data=data)m$formula <- Termsm[[1]] <- as.name("model.frame")m <- eval(m, parent.frame())if (NROW(m)==0)stop("No (non-missing) observations")if (missing(control)) control <- coxph.control(...)Y <- model.extract(m, "response")if (!inherits(Y, "Surv")) stop("Response must be a survival object")weights <- model.extract(m, 'weights')offset<- attr(Terms, "offset")tt <- length(offset)offset <- if(tt == 0)rep(0, nrow(Y))else if(tt == 1)m[[offset]]else {ff <- m[[offset[1]]]for(i in 2:tt)ff <- ff + m[[offset[i]]]ff}attr(Terms,"intercept")<- 1 #Cox model always has \Lambda_0strats <- attr(Terms, "specials")$stratacluster<- attr(Terms, "specials")$clusterdropx <- NULLif (length(cluster)) {if (missing(robust)) robust <- TRUEtempc <- untangle.specials(Terms, 'cluster', 1:10)ord <- attr(Terms, 'order')[tempc$terms]if (any(ord>1)) stop ("Cluster can not be used in an interaction")cluster <- strata(m[,tempc$vars], shortlabel=TRUE) #allow multiplesdropx <- tempc$terms}if (length(strats)) {temp <- untangle.specials(Terms, 'strata', 1)dropx <- c(dropx, temp$terms)if (length(temp$vars)==1) strata.keep <- m[[temp$vars]]else strata.keep <- strata(m[,temp$vars], shortlabel=TRUE)strats <- as.numeric(strata.keep)}##if (length(dropx)) X <- model.matrix(Terms[-dropx], m)[,-1,drop=F]##else X <- model.matrix(Terms, m)[,-1,drop=F]### this is inefficient, but subscripting loses the assign attributeif (length(dropx))newTerms<-Terms[-dropx]elsenewTerms<-TermsX<-model.matrix(newTerms,m)assign<-lapply(attrassign(X,newTerms)[-1],function(x) x-1)X<-X[,-1,drop=FALSE]type <- attr(Y, "type")if (type!='right' && type!='counting')stop(paste("Cox model doesn't support \"", type,"\" survival data", sep=''))if (missing(init)) init <- NULL# Check for penalized termspterms <- sapply(m, inherits, 'coxph.penalty')if (any(pterms)) {pattr <- lapply(m[pterms], attributes)## the 'order' attribute has the same components as 'term.labels'# pterms always has 1 more (response), sometimes 2 (offset)# drop the extra parts from ptermstemp <- c(attr(Terms, 'response'), attr(Terms, 'offset'))if (length(dropx)) temp <- c(temp, dropx+1)pterms <- pterms[-temp]temp <- match((names(pterms))[pterms], attr(Terms, 'term.labels'))ord <- attr(Terms, 'order')[temp]if (any(ord>1)) stop ('Penalty terms cannot be in an interaction')##pcols <- (attr(X, 'assign')[-1])[pterms]pcols<-assign[pterms]#penalized are hard sometimesif (control$eps.miss) control$eps <- 1e-7if (control$iter.miss) control$iter.max <- 20fit <- coxpenal.fit(X, Y, strats, offset, init=init,control,weights=weights, method=method,row.names(m), pcols, pattr, assign)}else {if( method=="breslow" || method =="efron") {if (type== 'right') fitter <- get("coxph.fit")else fitter <- get("agreg.fit")}else if (method=='exact') fitter <- get("agexact.fit")else stop(paste ("Unknown method", method))fit <- fitter(X, Y, strats, offset, init, control, weights=weights,method=method, row.names(m))}if (is.character(fit)) {fit <- list(fail=fit)class(fit) <- 'coxph'}else {if (!is.null(fit$coefficients) && any(is.na(fit$coefficients))) {vars <- (1:length(fit$coefficients))[is.na(fit$coefficients)]msg <-paste("X matrix deemed to be singular; variable",paste(vars, collapse=" "))if (singular.ok) warning(msg)else stop(msg)}fit$n <- nrow(Y)class(fit) <- fit$methodfit$terms <- Terms##fit$assign <- attr(X, 'assign')fit$assign<-assignif (robust) {fit$naive.var <- fit$varfit$method <- method# a little sneaky here: by calling resid before adding the# na.action method, I avoid having missings re-inserted# I also make sure that it doesn't have to reconstruct X and Yfit2 <- c(fit, list(x=X, y=Y, weights=weights))if (length(strats)) fit2$strata <- strata.keepif (length(cluster)) {temp <- residuals.coxph(fit2, type='dfbeta', collapse=cluster,weighted=TRUE)# get score for null modelif (is.null(init))fit2$linear.predictors <- 0*fit$linear.predictorselse fit2$linear.predictors <- c(X %*% init)temp0 <- residuals.coxph(fit2, type='score', collapse=cluster,weighted=TRUE)}else {temp <- residuals.coxph(fit2, type='dfbeta', weighted=TRUE)fit2$linear.predictors <- 0*fit$linear.predictorstemp0 <- residuals.coxph(fit2, type='score', weighted=TRUE)}fit$var <- t(temp) %*% tempu <- apply(as.matrix(temp0), 2, sum)fit$rscore <- coxph.wtest(t(temp0)%*%temp0, u, control$toler.chol)$test}#Wald testif (length(fit$coefficients) && is.null(fit$wald.test)) {#not for intercept only models, or if test is already donenabeta <- !is.na(fit$coefficients)if (is.null(init)) temp <- fit$coefficients[nabeta]else temp <- (fit$coefficients - init)[nabeta]fit$wald.test <- coxph.wtest(fit$var[nabeta,nabeta], temp,control$toler.chol)$test}na.action <- attr(m, "na.action")if (length(na.action)) fit$na.action <- na.actionif (model) fit$model <- m## else { ## we might want model=T and X=Tif (x) {fit$x <- Xif (length(strats)) fit$strata <- strata.keep}if (y) fit$y <- Y## }}if (!is.null(weights) && any(weights!=1)) fit$weights <- weights##fit$formula <- as.vector(attr(Terms, "formula"))fit$formula<-formula(Terms) ## get the environments rightfit$call <- callfit$method <- methodfit}