web-dev-qa-db-ja.com

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を実行すると、各因子の1レベルが参照レベルとして除外されます。ただし、すべての要因のすべてのレベルに対して、ダミー/インジケータ変数を使用してmatrixを作成します。私はglmnetのためにこの行列を構築しているので、多重共線性については心配していません。

model.matrixに要因のすべてのレベルのダミーを作成させる方法はありますか?

58
Jared

因子変数の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))))
46
fabians

(自分で引き換えようとしています...)Jaredの@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))
60
Gavin Simpson

caretは、ニース関数dummyVarsを実装して、2行でこれを実現します。

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/

13
pablo_sci

dummyVarscaretも使用できます。 http://caret.r-forge.r-project.org/preprocess.html

10
Sagar Jauhari

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
asdf123

OK。上記を読んで、まとめてください。マトリックスが必要だとします。係数ベクトルを乗算して線形予測子を取得する「X.factors」。まだいくつかの追加手順があります:

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

(ファクター列が1つしかない場合は、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))
2
user36302
model.matrix(~ First + Second + Third + Fourth + Fifth - 1, data=testFrame)

または

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

最も簡単なはずです

0
Federico Rotolo

statsパッケージの回答:

new_tr <- model.matrix(~.+0,data = testFrame)

Rのモデル式(たとえば、lm())に+0(または-1)を追加すると、切片が抑制されます。

ご覧ください

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
shosaco