Отбрасывание переменной в формуле lm все еще вызывает ошибку контраста

9

Я пытаюсь запустить lm () только на подмножестве моих данных, и сталкиваюсь с проблемой.

dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

lm( y ~ ., dt) # Use all x: Works
lm( y ~ ., dt[x3 == 'men']) # Use all x, limit to men: doesn't work (as expected)

Вышеупомянутое не работает, потому что в наборе данных теперь есть только мужчины, и поэтому мы не можем включить x3, гендерную переменную, в модель. НО...

lm( y ~ . -x3, dt[x3 == 'men']) # Exclude x3, limit to men: STILL doesn't work
lm( y ~ x1 + x2, dt[x3 == 'men']) # Exclude x3, with different notation: works great

Это проблема с обозначением «минус» в формуле? Пожалуйста посоветуй. Примечание: конечно, я могу сделать это по-другому; например, я мог бы исключить переменные до помещения их в lm (). Но я преподаю урок по этому вопросу, и я не хочу вводить студентов в заблуждение, уже сказав им, что они могут исключить переменную, используя знак минус в формуле.

Чжаочень хе
источник
3
Интересно, что и так model.matrix(y ~ . - x3, data = dt[x3 == "men"])и model.matrix(y ~ x1 + x2, data = dt[x3 == "men"])работает ( lmзвонит model.matrixвнутри). Единственное различие между обеими модельными матрицами заключается в "contrasts"атрибуте (который все еще содержится x3), который позже будет обнаружен в рамках lmподпрограммы, что, вероятно, приведет к появившейся ошибке. Поэтому я чувствую, что проблема связана с тем, как model.matrixсоздается и сохраняется матрица дизайна при удалении терминов.
Maurits Evers
Я пытался «развернуть», .чтобы получить упрощенную формулу, terms(y ~ . -x3, data=dt, simplify=TRUE)но, как ни странно, она все еще остается x3в атрибуте переменных, который срабатываетlm
MrFlick
1
@MrFlick - похоже, опция unimplemented-in-R neg.out=может быть связана. Из справочных файлов S для terms, где neg.out=реализовано: флаг, управляющий обработкой терминов, вводимых со знаком «-». Если TRUE, условия будут проверены на отмену и в противном случае проигнорированы. Если FALSE, отрицательные условия будут сохранены (с отрицательным порядком).
thelatemail
1
@MauritsEvers: lmвызывает model.matrixизмененную версию данных. В самом начале, lmсостовляющие и оценивает следующие выражения: mf <- stats::model.frame( y ~ . -x3, dt[x3=="men"], drop.unused.levels=TRUE ). Это заставляет x3стать одноуровневым фактором. model.matrix()затем вызывается mf, а не исходные данные, что приводит к ошибке, которую мы наблюдаем.
Артем Соколов

Ответы:

2

Ошибка, которую вы получаете, заключается в том, что x3 в модели только с одним значением = "men"(см. Комментарий ниже от @Artem Sokolov)

Один из способов решить эту проблему заключается в подмножестве заранее:

dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

dmen<-dt[x3 == 'men'] # create a new subsetted dataset with just men

lm( y ~ ., dmen[,-"x3"]) # now drop the x3 column from the dataset (just for the model)

Или вы можете сделать оба в одном шаге:

lm( y ~ ., dt[x3 == 'men',-"x3"])
Dylan_Gomes
источник
В целом, это хорошее решение. Единственное , что правильно, что -x3в формуле вовсе не вызывает lmдумать , что вы пытаетесь вычесть столбец. «Не использовать x3 в модели» намерение передается правильно, но проблема в том , что lmвызовы model.frame( ..., drop.unused.levels=TRUE )вызывая x3стать фактором одноуровневый, что приводит к проблемам в нижнем течении model.matrix().
Артем Соколов
Спасибо за разъяснения, Артем Соколов, я вычеркнул это неверное объяснение из своего ответа.
Dylan_Gomes