在R中定义线性模型时出现对比误差

时间:2013-08-11 11:04:47

标签: database r statistics

当我尝试在R中定义我的线性模型时如下:

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

我收到以下错误消息:

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

有没有办法忽略这个或修复它?有些变量是因素,有些则不是。

8 个答案:

答案 0 :(得分:51)

如果您的自变量(RHS变量)是一个因子或只占一个值的字符,则会发生该类型的错误。

示例:R

中的虹膜数据
(model1 <- lm(Sepal.Length ~ Sepal.Width + Species, data=iris))

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

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

现在,如果您的数据只包含一个物种:

(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

如果变量是数字(Sepal.Width),但只取一个值表示3,则模型会运行,但您将获得NA作为该变量的系数,如下所示:

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

# 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

解决方案:因变量的变化不足,只有一个值。因此,您需要删除该变量,无论是数字还是字符或因子变量。

根据评论更新:由于您知道错误只会发生在因子/字符上,因此您只能关注那些因素并查看这些因子变量的级别长度是否为1(DROP) )或大于1(NODROP)。

要查看变量是否为因子,请使用以下代码:

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

然后,您只能获得因子变量的数据框

m <- iris[, l]

现在,找到因子变量的级别数,如果这是你需要删除的那个

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

注意:如果因子变量的级别只有一个,那么这就是变量,你必须放弃。

答案 1 :(得分:14)

您的至少一个预测变量x1x2x3似乎只有一个因子级别,因此是常量。

看看

lapply(dataframe.df[c("x1", "x2", "x3")], unique)

找到不同的值。

答案 2 :(得分:3)

Metrics和Svens回答处理通常的情况,但对于我们在非英语环境中工作的人,如果你的角色变量中有异国情调(å,ä,ö)你会得到相同的结果,即使你有多个要素水平。

Levels <- c("Pri", "För")给出了对比度错误,而Levels <- c("Pri", "For")没有

这可能是一个错误。

答案 3 :(得分:2)

如果数据包含NA s。

,也可能会出现此错误消息

在这种情况下,行为取决于默认值(请参阅文档),并且可能会默默删除变量中提到的列中NA的所有情况。因此,一个因素确实可能有几个结果,但该因素在限制没有NA的情况时只有一个结果。

在这种情况下,要修复错误,请更改模型(从公式中删除有问题的因素),或更改数据(即完成案例)。

答案 4 :(得分:2)

其他作者的答案已经解决了只有一个水平或不适用的因素的问题。

今天,我在使用rstatix::anova_test()函数时偶然发现了相同的错误,但是我的因素还不错(一个以上的水平,没有NA,没有字符向量,...)。相反,我可以通过删除数据框中模型中未包括的所有变量来修复错误。我不知道此行为的原因是什么,但是仅在了解此错误时也可能会有所帮助。

答案 5 :(得分:0)

这是@Metrics提供的答案的变体,由@Max Ghenis编辑......

\\&

这里,在识别因子变量之后,第二个l <- sapply(iris, function(x) is.factor(x)) m <- iris[,l] n <- sapply( m, function(x) { y <- summary(x)/length(x) len <- length(y[y<0.005 | y>0.995]) cbind(len,t(y))} ) drop_cols_df <- data.frame(var = names(l[l]), status = ifelse(as.vector(t(n[1,]))==0,"NODROP","DROP" ), level1 = as.vector(t(n[2,])), level2 = as.vector(t(n[3,]))) 计算变量的每个级别/类别的记录百分比。然后它确定超过99.5%或低于0.5%发病率(我的任意阈值)的水平数。

然后继续返回每个分类变量中有效等级的数量和每个等级的发生率。

不应该删除零级别超过阈值的变量,而另一个应该从线性模型中删除。

最后一个数据框使查看结果变得容易。由于所有因子变量都是二项式的,因此对此数据集进行了硬编码。该数据框可以很容易地通用。

答案 6 :(得分:0)

如果错误恰好是由于您的数据具有NA,则您需要设置glm()函数选项,以了解如何处理NA案例。有关此问题的更多信息,请参见以下相关文章:https://stats.stackexchange.com/questions/46692/how-the-na-values-are-treated-in-glm-in-r

答案 7 :(得分:0)

根据我十分钟前的经验,这种情况可能发生在一个类别不止一个但NA较多的情况下。以Kaggle Houseprice Dataset为例, 如果您加载了数据并进行了简单的回归,

train.df = read.csv('train.csv')
lm1 = lm(SalePrice ~ ., data = train.df)

您将收到相同的错误。我还尝试测试每个因素的级别数,但没有一个说它低于2个级别。

cols = colnames(train.df)
for (col in cols){
  if(is.factor(train.df[[col]])){
    cat(col, ' has ', length(levels(train.df[[col]])), '\n')
  }
}

因此,很长一段时间后,我使用summary(train.df)来查看每个列的详细信息,并删除了一些列,终于可以了:

train.df = subset(train.df, select=-c(Id, PoolQC,Fence, MiscFeature, Alley, Utilities))
lm1 = lm(SalePrice ~ ., data = train.df)

并删除其中任何一个,回归将无法再次运行,并出现相同的错误(我已经对自己进行了测试)。

及以上属性通常具有1400多个NA和10个有用值,因此,即使它们具有3或4个级别,您也可能希望删除这些垃圾属性。我猜想有一个函数计算每列中有多少个NA会有所帮助。