Как отладить ошибку" контрасты могут применяться только к факторам с 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.

я рекомендую вам использовать их следующим образом.

  1. выполнить NA_preproc получить более полные случаи;
  2. запустите свою модель, и если вы получите "ошибку контрастов", используйте 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

модельный штуцер в группу и на как фактор уровни

если вы подгоняете модель по группе, вы с большей вероятностью получите "ошибку контрастов". вам нужно

  1. разделите фрейм данных по переменной группировки (см. ?split.data.frame);
  2. работа через эти фреймы данных один за другим, применяя debug_contr_error2 (lapply функция может быть полезна для выполнения этого цикла).

некоторые также сказали, что они не могут использовать na.omit по их данным, потому что это будет в конечном итоге слишком мало рядов, чтобы сделать что-то разумное. это можно расслабить. На практике это NA_integer_ и NA_real_ это нужно опустить, но NA_character_ можно сохранить: просто добавьте NA как уровень фактора. Для этого вам нужно перебрать переменные в фрейме данных:

  • если переменная x - это уже фактор и anyNA(x) is TRUE, do x <- addNA(x). Важно "и". Если x нет NA, addNA(x) добавит неиспользованный