Все уровни фактора в модельной матрице в R - PullRequest
57 голосов
/ 30 декабря 2010

У меня есть data.frame, состоящий из числовых и факторных переменных, как показано ниже.

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))

Я хочу создать matrix, который присваивает фиктивные переменные фактору и оставляет числовые переменные в покое..

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

Как и ожидалось, при запуске lm это оставляет один уровень каждого фактора в качестве опорного уровня.Тем не менее, я хочу построить matrix с фиктивной / индикаторной переменной для каждого уровня всех факторов.Я строю эту матрицу для glmnet, поэтому меня не беспокоит мультиколлинеарность.

Есть ли способ model.matrix создать фиктив для каждого уровня фактора?

Ответы [ 9 ]

60 голосов
/ 31 декабря 2010

(Пытаясь выкупить себя ...) В ответ на комментарий Джареда об ответе @Fabians об автоматизации, обратите внимание, что все, что вам нужно предоставить, это именованный список матриц контрастности. contrasts() берет вектор / фактор и создает из него матрицу контрастов. Для этого мы можем использовать lapply() для запуска contrasts() для каждого фактора в нашем наборе данных, например, для предоставленного примера testFrame:

> 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

Какая щель в ответ @fabians:

model.matrix(~ ., data=testFrame, 
             contrasts.arg = lapply(testFrame[,4:5], contrasts, contrasts=FALSE))
46 голосов
/ 30 декабря 2010

Вам необходимо сбросить contrasts для факторных переменных:

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

или, с чуть меньшим набором текста и без собственных имен:

model.matrix(~ Fourth + Fifth, data=testFrame, 
    contrasts.arg=list(Fourth=diag(nlevels(testFrame$Fourth)), 
            Fifth=diag(nlevels(testFrame$Fifth))))
13 голосов
/ 28 декабря 2016

caret реализована хорошая функция dummyVars для достижения этого с двумя строками:

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

Проверка последних столбцов:

colnames(testFrame2)

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

Самое приятное здесь то, что вы получаете исходный фрейм данных, плюс фиктивные переменные, исключающие исходные переменные, использованные для преобразования.

Дополнительная информация: http://amunategui.github.io/dummyVar-Walkthrough/

10 голосов
/ 14 марта 2013

dummyVars из caret также может быть использовано. http://caret.r -forge.r-project.org / preprocess.html

2 голосов
/ 15 января 2017

В настоящее время я изучаю модель Лассо и glmnet::cv.glmnet(), model.matrix() и Matrix::sparse.model.matrix() (для матрицы больших размеров, использование model.matrix убьет наше время, как предполагает автор glmnet.).

Просто поделиться там есть аккуратным кодированием, чтобы получить тот же ответ, что и @fabians и ответ @ Gavin.Между тем, @ asdf123 также представил еще один пакет 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 для всех: расширенная аналитика и графика (стр. 273)

2 голосов
/ 14 сентября 2016

Использование пакета 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 голосов
/ 24 июля 2014

Хорошо.Просто прочитав выше и собрав все это вместе.Предположим, вам нужна матрица, например, «X.factors», которая умножается на ваш коэффициент, чтобы получить ваш линейный предиктор.Есть еще пара дополнительных шагов:

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

(Обратите внимание, что вам нужно превратить X [*] обратно во фрейм данных, если у вас есть только один столбец фактора.)

Тогдаскажем, вы получите что-то вроде этого:

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

Мы хотим избавиться от ** эталонных уровней каждого фактора

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))
0 голосов
/ 16 февраля 2019

A tidyverse ответ:

library(dplyr)
library(tidyr)
result <- testFrame %>% 
    mutate(one = 1) %>% spread(Fourth, one, fill = 0, sep = "") %>% 
    mutate(one = 1) %>% spread(Fifth, one, fill = 0, sep = "")

дает желаемый результат (аналогично ответу @Gavin Simpson):

> head(result, 6)
  First Second Third FourthAlice FourthBob FourthCharlie FourthDavid FifthEdward FifthFrank FifthGeorgia FifthHank FifthIsaac
1     1      5     4           0         0             1           0           0          1            0         0          0
2     1     14    10           0         0             0           1           0          0            1         0          0
3     2      2     9           0         1             0           0           1          0            0         0          0
4     2      5     4           0         0             0           1           0          1            0         0          0
5     2     13     5           0         0             1           0           1          0            0         0          0
6     2     15     7           1         0             0           0           1          0            0         0          0
0 голосов
/ 04 сентября 2015
model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame)

или

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

должно быть самым простым

...