[英]Error in contrasts when defining a linear model in R
當我嘗試在 R 中定義我的線性 model 時,如下所示:
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
有什么辦法可以忽略或修復它嗎? 有些變量是因素,有些則不是。
如果您的自變量(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")
注意:如果因子變量的水平只有一個,那么這就是變量,你必須刪除。
您的預測變量中至少有一個x1
、 x2
或x3
似乎只有一個因子水平,因此是一個常數。
看一下
lapply(dataframe.df[c("x1", "x2", "x3")], unique)
找到不同的值。
當數據包含NA
時,也可能出現此錯誤消息。
在這種情況下,行為取決於默認值(請參閱文檔),並且可能會悄悄刪除變量中提到的列中包含NA
的所有情況。 因此,一個因素可能確實有多個結果,但是當限制為沒有NA
的情況時,該因素只有一個結果。
在這種情況下,要修復錯誤,要么更改模型(從公式中刪除有問題的因素),要么更改數據(即完成案例)。
其他作者的答案已經解決了只有一個級別或 NA 的因素問題。
今天,我在使用rstatix::anova_test()
函數時偶然發現了同樣的錯誤,但我的因素沒問題(不止一個級別,沒有 NA,沒有字符向量,......)。 相反,我可以通過刪除數據框中未包含在模型中的所有變量來修復錯誤。 我不知道這種行為的原因是什么,但在遇到此錯誤時,僅了解這一點也可能會有所幫助。
Metrics and Svens answer 處理通常的情況,但對於在非英語環境中工作的我們來說,如果您的字符變量中有異國情調的字符 (å,ä,ö),即使您有多個因子級別,您也會得到相同的結果。
Levels <- c("Pri", "För")
給出對比度誤差,而Levels <- c("Pri", "For")
沒有
這可能是一個錯誤。
如果錯誤恰好是因為您的數據具有 NA,那么您需要設置 glm() 函數選項,以說明您希望如何處理 NA 情況。 可以在此處的相關帖子中找到有關這方面的更多信息: https : //stats.stackexchange.com/questions/46692/how-the-na-values-are-treatment-in-glm-in-r
當某些值列是整數而其他值列是數字時,我遇到了同樣的問題。 將所有數字更改為 integer 解決了這個問題(不知道它是否影響分析)。
這是@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% 的發生率(我的任意閾值)的水平數。
然后繼續返回每個分類變量中有效級別的數量和每個級別的發生率。
零水平越過閾值的變量不應該被刪除,而另一個應該從線性模型中刪除。
最后一個數據框使查看結果變得容易。 由於所有因子變量都是二項式的,因此對這個數據集進行了硬編碼。 這個數據框可以很容易地變得通用。
根據我十分鍾前的經驗,這種情況可能發生在有多個類別但有很多 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)
查看每個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 的函數會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.