Все уровни фактора в модельной матрице в R
У меня есть 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
создать манекен для каждого уровня фактора?
Ответы
Ответ 1
Для фактор-переменных вам нужно reset 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))))
Ответ 2
(Попытка выкупить себя...) В ответ на комментарий Джареда о том, что @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))
Ответ 3
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/
Ответ 4
dummyVars
из caret
также может использоваться. http://caret.r-forge.r-project.org/preprocess.html
Ответ 5
Ok. Просто прочитав выше и все вместе. Предположим, вам нужна матрица, например. "X.факторы", которые умножаются на ваш коэффициентный вектор, чтобы получить ваш линейный предиктор. Есть еще несколько дополнительных шагов:
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
Мы хотим избавиться от эталонных уровней ** -d каждого фактора
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))
Ответ 6
Использование пакета 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
Ответ 7
В настоящее время я изучаю модели Лассо и glmnet::cv.glmnet()
, model.matrix()
и Matrix::sparse.model.matrix()
(для матрицы больших размеров, использование model.matrix
наше время, как предлагает автор glmnet
.).
Просто обмен там имеет аккуратную кодировку, чтобы получить тот же ответ, что и @fabians и @Gavin. Между тем, @asdf123 также представил еще одну library('CatEncoders')
пакетов 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)
Ответ 8
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
Ответ 9
model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame)
или же
model.matrix(~ First + Second + Third + Fourth + Fifth + 0, data=testFrame)
должно быть самым простым
Ответ 10
Ответ пакета stats
:
new_tr <- model.matrix(~.+0,data = testFrame)
Добавление +0 (или -1) к модельной формуле (например, в lm()) в R подавляет перехват.
Посмотри пожалуйста