Upuszczenie zmiennej w formule lm nadal powoduje błąd kontrastu

9

Próbuję uruchomić lm () tylko na podzbiorze moich danych i napotkałem problem.

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)

Powyższe nie działa, ponieważ w zestawie danych są teraz tylko mężczyźni, dlatego nie możemy włączyć do modelu zmiennej x3, zmiennej płci. ALE...

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

Czy to problem z notacją „znak minus” w formule? Proszę o poradę. Uwaga: Oczywiście mogę to zrobić w inny sposób; na przykład, mógłbym wykluczyć zmienne przed umieszczeniem ich w lm (). Ale prowadzę zajęcia na ten temat i nie chcę mylić uczniów, którzy już powiedzieli, że mogą wykluczyć zmienną za pomocą znaku minus w formule.

Zhaochen He
źródło
3
Interesujące jest to, że zarówno model.matrix(y ~ . - x3, data = dt[x3 == "men"])i model.matrix(y ~ x1 + x2, data = dt[x3 == "men"])praca ( lmpołączenia model.matrixwewnętrzne). Jedyną różnicą między obiema matrycami modelu jest "contrasts"atrybut (który wciąż zawiera x3), który zostaje później wykryty w lmprocedurze, prawdopodobnie powodując błąd, który widzisz. Mam więc wrażenie, że problem dotyczy sposobu model.matrixtworzenia i przechowywania matrycy projektu podczas usuwania terminów.
Maurits Evers
Próbowałem „rozwinąć”, .aby uzyskać uproszczoną formułę, terms(y ~ . -x3, data=dt, simplify=TRUE)ale dziwnie nadal zachowuje x3atrybut zmiennych, który się lm
wyłącza
1
@MrFlick - wygląda na to, że neg.out=opcja niezaimplementowana w R może być powiązana. Z plików pomocy S dla terms, gdzie neg.out=jest zaimplementowany: flaga kontrolująca sposób traktowania haseł wprowadzanych znakiem „-”. Jeśli PRAWDA, warunki zostaną sprawdzone pod kątem anulowania i w inny sposób zignorowane. Jeśli FAŁSZ, negatywne warunki zostaną zachowane (w kolejności ujemnej).
thelatemail
1
@MauritsEvers: lmwywołuje model.matrixzmodyfikowaną wersję danych. Na samym początku, lmkomponuje i ocenia następujące wyrażenie: mf <- stats::model.frame( y ~ . -x3, dt[x3=="men"], drop.unused.levels=TRUE ). To powoduje, x3że staje się czynnikiem jednopoziomowym. model.matrix()są następnie wywoływane mf, a nie oryginalne dane, co powoduje błąd, który obserwujemy.
Artem Sokolov

Odpowiedzi:

2

Występuje błąd, ponieważ x3 jest w modelu z tylko jedną wartością = "men"(patrz komentarz poniżej z @Artem Sokolov)

Jednym ze sposobów rozwiązania tego jest podzbiór z wyprzedzeniem:

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)

Lub możesz zrobić oba w tym samym kroku:

lm( y ~ ., dt[x3 == 'men',-"x3"])
Dylan_Gomes
źródło
Ogólnie rzecz biorąc, jest to dobre rozwiązanie. Jedną rzeczą do poprawienia jest to, że -x3w formule nie powoduje lm, że próbujesz odjąć kolumnę. W „nie używaj x3 w modelu” intencją jest przekazywana poprawnie, ale problem jest to, że lmrozmowy model.frame( ..., drop.unused.levels=TRUE )spowodowanie x3, aby stać się czynnikiem single-level, co prowadzi do dalszych problemów model.matrix().
Artem Sokolov
Dziękuję za wyjaśnienie Artem Sokołow, wyciągnąłem to nieprawidłowe wyjaśnienie z mojej odpowiedzi.
Dylan_Gomes