REnthusiast REnthusiast - 1 month ago 10
R Question

Error in contrasts when defining a linear model in R

When I try to define my linear model in R as follows:

lm1 <- lm(predictorvariable ~ x1+x2+x3, data=dataframe.df)


I get the following error message:

Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) :
contrasts can be applied only to factors with 2 or more levels


Is there any way to ignore this or fix it? Some of the variables are factors and some are not.

Answer

If your independent variable (RHS variable) is a factor or a character taking only one value then that type of error occurs.

Example: iris data in R

model1<-lm(Sepal.Length~Sepal.Width+Species,data=iris)
> model1

Call:
lm(formula = Sepal.Length ~ Sepal.Width + Species, data = iris)

Coefficients:
      (Intercept)        Sepal.Width  Speciesversicolor   Speciesvirginica  
           2.2514             0.8036             1.4587             1.9468  

Now, if your data consists of only one species:

model1<-lm(Sepal.Length~Sepal.Width+Species,data=iris[iris$Species=="setosa",])
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels

If the variable is numeric (Sepal.Width) but taking only a single value say 3, then the model runs but you will get NA as coefficient of that variable as follows:

model2<-lm(Sepal.Length~Sepal.Width+Species,data=iris[iris$Sepal.Width==3,])
> model2

Call:
lm(formula = Sepal.Length ~ Sepal.Width + Species, data = iris[iris$Sepal.Width == 
    3, ])

Coefficients:
      (Intercept)        Sepal.Width  Speciesversicolor   Speciesvirginica  
            4.700                 NA              1.250              2.017

Solution: There is no enough variation in dependent variable with only one value. So, you need to drop that variable, irrespective of whether that is numeric or character or factor variable.

Updated as per comments: Since you know that the error will only occur with factor/character, you can focus only on those and see whether the length of levels of those factor variables is 1 (DROP) or greater than 1 (NODROP).

To see, whether the variable is a factor or not, use the following code:

l<-sapply(iris,function(x)is.factor(x))
>l
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
       FALSE        FALSE        FALSE        FALSE         TRUE 

Then you can get the data frame of factor variables only

m<-iris[,names(which(l=="TRUE"))]

Now, find the number of levels of factor variables, if this is one you need to drop that

ifelse(n<-sapply(m,function(x)length(levels(x)))==1,"DROP","NODROP")

Note: If the levels of factor variable is only one then that is the variable, you have to drop.