当我尝试在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
有没有办法忽略这个或修复它?有些变量是因素,有些则不是。
答案 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)
您的至少一个预测变量x1
,x2
或x3
似乎只有一个因子级别,因此是常量。
看看
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会有所帮助。