Как отладить ошибку" контрасты могут применяться только к факторам с 2 или более уровнями"?
вот все переменные, с которыми я работаю:
str(ad.train)
$ Date : Factor w/ 427 levels "2012-03-24","2012-03-29",..: 4 7 12 14 19 21 24 29 31 34 ...
$ Team : Factor w/ 18 levels "Adelaide","Brisbane Lions",..: 1 1 1 1 1 1 1 1 1 1 ...
$ Season : int 2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
$ Round : Factor w/ 28 levels "EF","GF","PF",..: 5 16 21 22 23 24 25 26 27 6 ...
$ Score : int 137 82 84 96 110 99 122 124 49 111 ...
$ Margin : int 69 18 -56 46 19 5 50 69 -26 29 ...
$ WinLoss : Factor w/ 2 levels "0","1": 2 2 1 2 2 2 2 2 1 2 ...
$ Opposition : Factor w/ 18 levels "Adelaide","Brisbane Lions",..: 8 18 10 9 13 16 7 3 4 6 ...
$ Venue : Factor w/ 19 levels "Adelaide Oval",..: 4 7 10 7 7 13 7 6 7 15 ...
$ Disposals : int 406 360 304 370 359 362 365 345 324 351 ...
$ Kicks : int 252 215 170 225 221 218 224 230 205 215 ...
$ Marks : int 109 102 52 41 95 78 93 110 69 85 ...
$ Handballs : int 154 145 134 145 138 144 141 115 119 136 ...
$ Goals : int 19 11 12 13 16 15 19 19 6 17 ...
$ Behinds : int 19 14 9 16 11 6 7 9 12 6 ...
$ Hitouts : int 42 41 34 47 45 70 48 54 46 34 ...
$ Tackles : int 73 53 51 76 65 63 65 67 77 58 ...
$ Rebound50s : int 28 34 23 24 32 48 39 31 34 29 ...
$ Inside50s : int 73 49 49 56 61 45 47 50 49 48 ...
$ Clearances : int 39 33 38 52 37 43 43 48 37 52 ...
$ Clangers : int 47 38 44 62 49 46 32 24 31 41 ...
$ FreesFor : int 15 14 15 18 17 15 19 14 18 20 ...
$ ContendedPossessions: int 152 141 149 192 138 164 148 151 160 155 ...
$ ContestedMarks : int 10 16 11 3 12 12 17 14 15 11 ...
$ MarksInside50 : int 16 13 10 8 12 9 14 13 6 12 ...
$ OnePercenters : int 42 54 30 58 24 56 32 53 50 57 ...
$ Bounces : int 1 6 4 4 1 7 11 14 0 4 ...
$ GoalAssists : int 15 6 9 10 9 12 13 14 5 14 ...
вот glm, который я пытаюсь подогнать:
ad.glm.all <- glm(WinLoss ~ factor(Team) + Season + Round + Score + Margin + Opposition + Venue + Disposals + Kicks + Marks + Handballs + Goals + Behinds + Hitouts + Tackles + Rebound50s + Inside50s+ Clearances+ Clangers+ FreesFor + ContendedPossessions + ContestedMarks + MarksInside50 + OnePercenters + Bounces+GoalAssists,
data = ad.train, family = binomial(logit))
Я знаю, что это много переменных (план состоит в том, чтобы уменьшить с помощью прямого выбора переменных). Но даже знаю, что это много переменных, они либо int, либо Factor; которые, как я понимаю, должны просто работать с glm. Однако каждый раз, когда я пытаюсь соответствовать этой модели, я получаю:
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels
какой вид выглядит для меня, как будто R не обрабатывает мой фактор переменные как факторные переменные по какой-то причине?
даже что-то простое, как:
ad.glm.test <- glm(WinLoss ~ factor(Team), data = ad.train, family = binomial(logit))
не работает! (то же сообщение об ошибке)
где:
ad.glm.test <- glm(WinLoss ~ Clearances, data = ad.train, family = binomial(logit))
будет работать!
кто-нибудь знает, что здесь происходит? Почему я не могу подогнать эти факторные переменные к моему glm??
спасибо заранее!
-Трой
1 ответов
введение
что такое "ошибка контрастов" хорошо объяснено: у вас есть фактор, который имеет только один уровень (или меньше). Но на самом деле этот простой факт может быть легко скрыт, потому что данные, которые фактически используются для подгонки модели, могут сильно отличаться от того, что вы передали. Это происходит, когда у вас есть NA
в ваших данных вы вложили свои данные, фактор имеет неиспользуемые уровни или вы преобразовали свои переменные и получите NaN
где-то. вы редко находитесь в этой идеальной ситуации, когда одноуровневый фактор может быть замечен из str(your_data_frame)
напрямую. многие вопросы по StackOverflow относительно этой ошибки не воспроизводимы, поэтому предложения людей могут или не могут работать. Поэтому, хотя есть к настоящему времени 118 должности что касается этой проблемы, пользователи по-прежнему не могут найти адаптивное решение, чтобы этот вопрос поднимался снова и снова. Этот ответ-моя попытка решить этот вопрос " однажды для всех" или, по крайней мере, обеспечить разумное руководство.
этот ответ имеет богатую информацию, поэтому позвольте мне сначала сделать краткое резюме.
я определил 3 вспомогательные функции для вас: debug_contr_error
, debug_contr_error2
, NA_preproc
.
я рекомендую вам использовать их следующим образом.
- выполнить
NA_preproc
получить более полные случаи; - запустите свою модель, и если вы получите "ошибку контрастов", используйте
debug_contr_error2
для отладка.
большинство ответов показывает вам шаг за шагом, как и почему эти функции определены. Вероятно, нет никакого вреда пропустить этот процесс разработки, но не пропускайте разделы из "воспроизводимых тематических исследований и обсуждений".
пересмотренный ответ
на оригинальный ответ отлично работает для OP и успешно помог некоторым другим. Но!--182-->он не где-то еще из-за отсутствия адаптивности. Посмотрите на выход str(ad.train)
в этом вопросе. Переменные OP являются числовыми или факторами; нет символов. Первоначальный ответ был для этой ситуации. Если у вас есть символьные переменные, хотя они будут принуждаться к факторам во время lm
и glm
фитинг, они не будут сообщаться кодом, так как они не были предоставлены в качестве факторов так is.factor
будет скучать по ним. В этом расширении я сделаю оригинальный ответ как больше адаптивный.
пусть dat
ваш набор данных передается в lm
или glm
. Если у вас нет такого фрейма данных, то есть все ваши переменные разбросаны в глобальной среде, вам нужно собрать их в фрейм данных. Возможно, это не лучший способ, но он работает.
## `form` is your model formula, here is an example
y <- x1 <- x2 <- x3 <- 1:4
x4 <- matrix(1:8, 4)
form <- y ~ bs(x1) + poly(x2) + I(1 / x3) + x4
## to gather variables `model.frame.default(form)` is the easiest way
## but it does too much: it drops `NA` and transforms variables
## we want something more primitive
## first get variable names
vn <- all.vars(form)
#[1] "y" "x1" "x2" "x3" "x4"
## `get_all_vars(form)` gets you a data frame
## but it is buggy for matrix variables so don't use it
## instead, first use `mget` to gather variables into a list
lst <- mget(vn)
## don't do `data.frame(lst)`; it is buggy with matrix variables
## need to first protect matrix variables by `I()` then do `data.frame`
lst_protect <- lapply(lst, function (x) if (is.matrix(x)) I(x) else x)
dat <- data.frame(lst_protect)
str(dat)
#'data.frame': 4 obs. of 5 variables:
# $ y : int 1 2 3 4
# $ x1: int 1 2 3 4
# $ x2: int 1 2 3 4
# $ x3: int 1 2 3 4
# $ x4: 'AsIs' int [1:4, 1:2] 1 2 3 4 5 6 7 8
## note the 'AsIs' for matrix variable `x4`
## in comparison, try the following buggy ones yourself
str(get_all_vars(form))
str(data.frame(lst))
Шаг 0: явное подмножество
если вы использовали пример преобразования.
debug_contr_error2(y ~ log(x) + f, dat)
#$mf
# y log(x) f
#1 1 0.0000000 a
#2 2 0.6931472 a
#3 3 1.0986123 a
#
#$nlevels
#f
#1
#
#$levels
#$levels$f
#[1] "a"
#
#
#Warning message:
#In log(x) : NaNs produced
попробовать subset_vec
как хорошо.
## or: debug_contr_error2(y ~ log(x) + f, dat, c(T, F, T, T))
debug_contr_error2(y ~ log(x) + f, dat, c(1,3,4))
#$mf
# y log(x) f
#1 1 0.000000 a
#3 3 1.098612 a
#
#$nlevels
#f
#1
#
#$levels
#$levels$f
#[1] "a"
#
#
#Warning message:
#In log(x) : NaNs produced
модельный штуцер в группу и на как фактор уровни
если вы подгоняете модель по группе, вы с большей вероятностью получите "ошибку контрастов". вам нужно
- разделите фрейм данных по переменной группировки (см.
?split.data.frame
); - работа через эти фреймы данных один за другим, применяя
debug_contr_error2
(lapply
функция может быть полезна для выполнения этого цикла).
некоторые также сказали, что они не могут использовать na.omit
по их данным, потому что это будет в конечном итоге слишком мало рядов, чтобы сделать что-то разумное. это можно расслабить. На практике это NA_integer_
и NA_real_
это нужно опустить, но NA_character_
можно сохранить: просто добавьте NA
как уровень фактора. Для этого вам нужно перебрать переменные в фрейме данных:
- если переменная
x
- это уже фактор иanyNA(x)
isTRUE
, dox <- addNA(x)
. Важно "и". Еслиx
нетNA
,addNA(x)
добавит неиспользованный