56

当我尝试在 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 

有什么办法可以忽略或修复它?有些变量是因素,有些不是。

4

9 回答 9

74

如果您的自变量(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如果变量是数字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")

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

于 2013-08-11T11:12:30.363 回答
18

x1似乎您的预测变量、x2、 或中至少有一个x3只有一个因子水平,因此是一个常数。

看一下

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

找到不同的值。

于 2013-08-11T11:13:12.327 回答
8

NA当数据包含s时,也可能出现此错误消息。

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

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

于 2017-11-28T16:59:14.333 回答
6

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

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

于 2020-04-02T16:08:38.027 回答
3

Metrics and Svens 的回答处理的是通常情况,但对于在非英语环境中工作的我们来说,如果您的字符变量中有外来字符 (å,ä,ö),即使您有多个因子级别,您也会得到相同的结果。

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

这可能是一个错误。

于 2016-10-20T07:09:04.903 回答
1

这是@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,])))

在这里,在识别因子变量之后,第二个sapply计算记录的百分比属于变量的每个级别/类别。然后它确定发生率超过 99.5% 或低于 0.5% 的水平数(我的任意阈值)。

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

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

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

于 2017-11-07T07:52:30.853 回答
1

如果错误恰好是因为您的数据具有 NA,那么您需要设置 glm() 函数选项,以了解您希望如何处理 NA 案例。有关这方面的更多信息,请参见此处的相关帖子:https ://stats.stackexchange.com/questions/46692/how-the-na-values-are-treatment-in-glm-in-r

于 2019-03-24T23:31:18.613 回答
1

当某些值列是整数而其他列是数字时,我遇到了同样的问题。将所有数字更改为整数解决了这个问题(不知道它是否会影响分析)。

于 2021-09-26T12:54:16.843 回答
1

根据我十分钟前的经验,这种情况可能发生在有多个类别但有很多 NA 的情况下。以Kaggle Houseprice 数据集为例,如果你加载数据并运行一个简单的回归,

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)查看每个 col 的详细信息,并删除了一些,它终于起作用了:

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

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

而以上属性一般有 1400+ NAs 和 10 个有用的值,所以你可能想要删除这些垃圾属性,即使它们有 3 或 4 个级别。我猜想计算每列中有多少 NA 的函数会有所帮助。

于 2020-03-01T16:12:05.583 回答