2

I have composed a function to calculate VIF for nls regression models. It looks like this:

function (a,b,c,d,e,f,g) {
    VIFa <- 1/(1- (R2 <- summary(lm(a ~ b + c + d + e + f + g))$r.square))
    PMa <- ifelse (sqrt(VIFa) > 2, "JE", "NI")
    VIFb <- 1/(1- (R2 <- summary(lm(b ~ a + c + d + e + f + g))$r.square))
    PMb <- ifelse (sqrt(VIFb) > 2, "JE", "NI")
    VIFc <- 1/(1- (R2 <- summary(lm(c ~ a + b + d + e + f + g))$r.square))
    PMc <- ifelse (sqrt(VIFc) > 2, "JE", "NI")
    VIFd <- 1/(1- (R2 <- summary(lm(d ~ a + b + c + e + f + g))$r.square))
    PMd <- ifelse (sqrt(VIFd) > 2, "JE", "NI")
    VIFe <- 1/(1- (R2 <- summary(lm(e ~ a + b + c + d + f + g))$r.square))
    PMe <- ifelse (sqrt(VIFe) > 2, "JE", "NI")
    VIFf <- 1/(1- (R2 <- summary(lm(f ~ a + b + c + d + e + g))$r.square))
    PMf <- ifelse (sqrt(VIFf) > 2, "JE", "NI")
    VIFg <- 1/(1- (R2 <- summary(lm(g ~ a + b + c + d + e + f))$r.square))
    PMg <- ifelse (sqrt(VIFg) > 2, "JE", "NI")
    rezultat <- data.frame(c(VIFa, VIFb, VIFc, VIFd, VIFe, VIFf, VIFg), 
                           c(PMa, PMb, PMc, PMd, PMe, PMf, PMg)) 
    names(rezultat) <- c("VIF", "Multikolinearnost")
    return(as.matrix.data.frame(rezultat))
    }

Where a,b,c,d,e,f,g are variables that are used in certain model. VIFa is Variance Inflation Factor of 'a' variable, and PMa is a logical value showing whether variance inflation can cause major discrepancy in model (JE = yes) or not (NO = not).

My question is how to make this function suitable for any number of arguments? I already tried to use lapply function, however I could not find a way to use each variable once as dependent and all others as independent (for any number of variables).

1
  • How does the function know that there are no squared, interaction terms etc. in your formula? The variable names alone do not properly define the regression model. Commented Sep 14, 2014 at 9:32

2 Answers 2

1

Try the following:

regapply <- function(l) {
   ids <- names(l)
   n <- length(l)
   vifs <- numeric(n)
   pms <- character(n)
   for (i in seq_along(l)) {
      f <- parse(text=sprintf("%s ~ %s", ids[i], paste(ids[-i], collapse=" + ")))[[1]]
      vifs[i] <- 1/(1- (R2 <- summary(lm(f, data=l))$r.square))
      pms[i] <- ifelse (sqrt(vifs[i]) > 2, "JE", "NI")
   }
   data.frame(var=ids, vif=vifs, pm=pms)
}

Call the above on a named list (e.g. a data frame), for example:

regapply(iris[-5])
##            var       vif pm
## 1 Sepal.Length  7.072722 JE
## 2  Sepal.Width  2.100872 NI
## 3 Petal.Length 31.261498 JE
## 4  Petal.Width 16.090175 JE

Explanation: parse(text=sprintf("%s ~ %s", ids[i], paste(ids[-i], collapse=" + ")))[[1]] creates a series of formulas. In the above example we have:

Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width
Sepal.Width ~ Sepal.Length + Petal.Length + Petal.Width
Petal.Length ~ Sepal.Length + Sepal.Width + Petal.Width
Petal.Width ~ Sepal.Length + Sepal.Width + Petal.Length
Sign up to request clarification or add additional context in comments.

Comments

1

Here is another solution using an ellipsis for the varying number of arguments.

The regression models that you apply contain solely additive terms (see my comment on your question). In this case, you can loop over the variables (e.g. in a data.frame).

vif <- function(...){
  dat <- data.frame(...)
  n <- ncol(dat)

  out <- data.frame(VIF=numeric(n), MK=numeric(n))
  for(ii in 1:n){
    dv <- colnames(dat)[ii]
    iv <- colnames(dat)[-ii]
    fml <- as.formula(paste(dv,paste(iv,collapse="+"),sep="~"))

    VIF <- 1/(1- (R2 <- summary(lm(fml))$r.square))
    KM <- ifelse(sqrt(VIF)>2, "JE", "NI")
    out[ii,] <- c(round(VIF,5),KM)
  }
  return(out)
}

Works for both variables and data.frames as input.

a <- c(1,2,3,4,5)
b <- c(1,3,2,2,4)
x <- c(3,3,2,4,5)
dat <- data.frame(a,b,x)

# > vif(a,b,x)
#       VIF MK
# 1 2.47059 NI
# 2 2.06471 NI
# 3 2.06471 NI
# > vif(dat)
#       VIF MK
# 1 2.47059 NI
# 2 2.06471 NI
# 3 2.06471 NI

Cheers!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.