簡體   English   中英

在 R 中定義線性 model 時出現對比錯誤

[英]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")

注意:如果因子變量的水平只有一個,那么這就是變量,你必須刪除。

您的預測變量中至少有一個x1x2x3似乎只有一個因子水平,因此是一個常數。

看一下

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM