R/lm.var.select.R

Defines functions lm.var.select

Documented in lm.var.select

#' Variable selection for linear models by backward selection. Original code at: http://stackoverflow.com/questions/19226816/how-can-i-view-the-source-code-for-a-function. Some changes have been done.
#' 
#' @param model a linear model (an object of class "lm") with the full model.
#' @param keep a list of model terms to keep in the model at all times.
#' @param sig significant level for removal of a variable.
#' @param method method for variable removal.
#' @param k a numeric value for penalizing number of variables with information criteria. Default value es 2, corresponding to Akaike Information Criteria.
#' @param verbose logical. Should R report information (dropped variable and resulting model) on progress? Default value is FALSE.
#' @param ... further arguments to be passed to or from methods.
#' @return Proposed final model.
#' @export
lm.var.select <- function(model, keep, method = c("none", "Chisq", "F"), k = 2, sig=0.05, verbose=F, ...){
  counter=1
  # check input
  if(!is(model,"lm")) stop(paste(deparse(substitute(model)),"is not an lm object\n"))
  # calculate scope for drop1 function
  terms <- attr(model$terms,"term.labels")
  if(missing(keep)){ # set scopevars to all terms
    scopevars <- terms
  } else{            # select the scopevars if keep is used
    index <- match(keep,terms)
    # check if all is specified correctly
    if(sum(is.na(index))>0){
      novar <- keep[is.na(index)]
      warning(paste(
        c(novar,"cannot be found in the model",
          "\nThese terms are ignored in the model selection."),
        collapse=" "))
      index <- as.vector(na.omit(index))
    }
    scopevars <- terms[-index]
  }
  
  # Backward model selection : 
  
  while(T){
    # extract the test statistics from drop.
    test <- drop1(model, scope=scopevars, test = method, k = k)
    
    if(verbose){
      cat("-------------STEP ",counter,"-------------\n",
          "The drop statistics : \n")
      print(test)
    }
    
    pval <- test[,dim(test)[2]]
    
    names(pval) <- rownames(test)
    pval <- sort(pval, decreasing=T)
    
    if(sum(is.na(pval))>0) stop(paste("Model",
                                      deparse(substitute(model)),"is invalid. Check if all coefficients are estimated."))
    
    # check if all significant
    if(pval[1]<sig) break # stops the loop if all remaining vars are sign.
    
    # select var to drop
    i=1
    while(T){
      dropvar <- names(pval)[i]
      check.terms <- terms[-match(dropvar,terms)]
      x <- has.interaction(dropvar,check.terms)
      if(x){i=i+1;next} else {break}              
    } # end while(T) drop var
    
    if(pval[i]<sig) break # stops the loop if var to remove is significant
    
    if(verbose){
      cat("\n--------\nTerm dropped in step",counter,":",dropvar,"\n--------\n\n")              
    }
    
    #update terms, scopevars and model
    scopevars <- scopevars[-match(dropvar,scopevars)]
    terms <- terms[-match(dropvar,terms)]
    
    formul <- as.formula(paste(".~.-",dropvar))
    model <- update(model,formul)
    
    if(length(scopevars)==0) {
      warning("All variables are thrown out of the model.\n",
              "No model could be specified.")
      return()
    }
    counter=counter+1
  } # end while(T) main loop
  return(model)
}
IRBLleida/UdBRpackage documentation built on Dec. 24, 2019, 9:10 p.m.