Wszystkie poziomy czynnika w macierzy modelu w R

Mam data.frame składający się ze zmiennych liczbowych i współczynnikowych, jak widać poniżej.

testFrame <- data.frame(First=sample(1:10, 20, replace=T),
           Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T),
           Fourth=rep(c("Alice","Bob","Charlie","David"), 5),
           Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4))

Chcę zbudować matrix, który przyporządkowuje zmienne obojętne do czynnika i pozostawia zmienne numeryczne same.

model.matrix(~ First + Second + Third + Fourth + Fifth, data=testFrame)

Zgodnie z oczekiwaniami przy uruchamianiu lm to pozostawia jeden poziom każdego czynnika jako poziom odniesienia. Jednak chcę zbudować matrix z zmienną manekina / wskaźnik dla każdego poziomu wszystkich czynników. Buduję tę matrycę dla glmnet, więc nie martwię się o wielokolinearność.

Czy istnieje sposób, aby model.matrix stworzyć atrapę dla każdego poziomu czynnika?

Author: sjakobi, 2010-12-30

8 answers

Musisz zresetować contrasts dla zmiennych czynnika:

model.matrix(~ Fourth + Fifth, data=testFrame, 
        contrasts.arg=list(Fourth=contrasts(testFrame$Fourth, contrasts=F), 
                Fifth=contrasts(testFrame$Fifth, contrasts=F)))

Lub, z nieco mniejszą literówką i bez nazw własnych:

model.matrix(~ Fourth + Fifth, data=testFrame, 
    contrasts.arg=list(Fourth=diag(nlevels(testFrame$Fourth)), 
            Fifth=diag(nlevels(testFrame$Fifth))))
 43
Author: fabians,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-30 09:38:21

(próbuje się odkupić...) W odpowiedzi na komentarz Jareda na @Fabians odpowiedz na temat automatyzacji, zauważ, że wszystko, co musisz podać, to imienna lista matryc kontrastu. contrasts() pobiera wektor / czynnik i tworzy z niego macierz kontrastów. W tym celu możemy użyć lapply() do uruchomienia contrasts() dla każdego czynnika w naszym zbiorze danych, np. dla przykładu testFrame podanego:

> lapply(testFrame[,4:5], contrasts, contrasts = FALSE)
$Fourth
        Alice Bob Charlie David
Alice       1   0       0     0
Bob         0   1       0     0
Charlie     0   0       1     0
David       0   0       0     1

$Fifth
        Edward Frank Georgia Hank Isaac
Edward       1     0       0    0     0
Frank        0     1       0    0     0
Georgia      0     0       1    0     0
Hank         0     0       0    1     0
Isaac        0     0       0    0     1

Który ładnie pasuje do @ fabians odpowiedz:

model.matrix(~ ., data=testFrame, 
             contrasts.arg = lapply(testFrame[,4:5], contrasts, contrasts=FALSE))
 57
Author: Gavin Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 16:59:48

dummyVars z caret może być również używany. http://caret.r-forge.r-project.org/preprocess.html

 10
Author: Sagar Jauhari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-14 02:29:10

caret zaimplementowano funkcję nice dummyVars, aby osiągnąć to za pomocą 2 linii:

library(caret) dmy <- dummyVars(" ~ .", data = testFrame) testFrame2 <- data.frame(predict(dmy, newdata = testFrame))

Sprawdzanie końcowych kolumn:

colnames(testFrame2)

"First"  "Second"         "Third"          "Fourth.Alice"   "Fourth.Bob"     "Fourth.Charlie" "Fourth.David"   "Fifth.Edward"   "Fifth.Frank"   "Fifth.Georgia"  "Fifth.Hank"     "Fifth.Isaac"   

Najładniejszym punktem jest to, że otrzymujesz oryginalną ramkę danych, plus fałszywe zmienne, które wykluczyły oryginalne używane do transformacji.

Więcej informacji: http://amunategui.github.io/dummyVar-Walkthrough/

 10
Author: pablo_sci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 18:08:50

Ok. Wystarczy przeczytać powyższe i złożyć to wszystko w całość. Załóżmy, że chcesz mieć macierz np. 'X. współczynniki', która mnoży się przez twój wektor współczynnika, aby otrzymać twój predyktor liniowy. Jest jeszcze kilka dodatkowych kroków:

X.factors = 
  model.matrix( ~ ., data=X, contrasts.arg = 
    lapply(data.frame(X[,sapply(data.frame(X), is.factor)]),
                                             contrasts, contrasts = FALSE))

(zauważ, że musisz zamienić X [*] z powrotem w ramkę danych, jeśli masz tylko jedną kolumnę czynników.)

To powiedz, że masz coś takiego:

attr(X.factors,"assign")
[1]  0  1  **2**  2  **3**  3  3  **4**  4  4  5  6  7  8  9 10 #emphasis added

Chcemy pozbyć się * * ' D poziomów referencyjnych każdego czynnika

att = attr(X.factors,"assign")
factor.columns = unique(att[duplicated(att)])
unwanted.columns = match(factor.columns,att)
X.factors = X.factors[,-unwanted.columns]
X.factors = (data.matrix(X.factors))
 2
Author: user36302,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 18:11:57

Używanie pakietu r 'CatEncoders'

library(CatEncoders)
testFrame <- data.frame(First=sample(1:10, 20, replace=T),
           Second=sample(1:20, 20, replace=T), Third=sample(1:10, 20, replace=T),
           Fourth=rep(c("Alice","Bob","Charlie","David"), 5),
           Fifth=rep(c("Edward","Frank","Georgia","Hank","Isaac"),4))

fit <- OneHotEncoder.fit(testFrame)

z <- transform(fit,testFrame,sparse=TRUE) # give the sparse output
z <- transform(fit,testFrame,sparse=FALSE) # give the dense output
 2
Author: asdf123,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-14 01:56:17
model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame)

Lub

model.matrix(~ First + Second + Third + Fourth + Fifth + 0, data=testFrame)

Powinno być najprościej

F

 1
Author: Federico Rotolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-04 08:05:07

[7]}obecnie uczę się Modelu Lasso i glmnet::cv.glmnet(), model.matrix() i Matrix::sparse.model.matrix()(dla macierzy dużych wymiarów, użycie model.matrix zabije nasz czas zgodnie z sugestią autora glmnet.).

Samo dzielenie się tam ma uporządkowane kodowanie, aby uzyskać taką samą odpowiedź jak odpowiedź @fabians i @ Gavin. W międzyczasie @ asdf123 wprowadził również inny pakiet library('CatEncoders').

> require('useful')
> # always use all levels
> build.x(First ~ Second + Fourth + Fifth, data = testFrame, contrasts = FALSE)
> 
> # just use all levels for Fourth
> build.x(First ~ Second + Fourth + Fifth, data = testFrame, contrasts = c(Fourth = FALSE, Fifth = TRUE))

Źródło : R dla każdego: zaawansowana analityka i grafika (page273)

 1
Author: RYO ENG Lian Hu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-24 07:13:34