数式とデータフレームがあり、model.matrix()
を抽出したいと思います。ただし、元のデータセットで見つかったNAを含めるために結果のマトリックスが必要です。これを行うためにmodel.frame()
を使用する場合は、単に_na.action=NULL
_を渡します。ただし、必要な出力はmodel.matrix()
形式です。具体的には、右側の変数のみが必要であり、出力は行列(データフレームではない)である必要があり、因子を一連のダミー変数に変換する必要があります。
ループなどを使って何かを一緒にハックできると確信していますが、もっとクリーンで効率的な回避策を誰かが提案できるかどうか疑問に思いました。どうもありがとうございました!
そしてここに例があります:
_dat <- data.frame(matrix(rnorm(20),5,4), gl(5,2))
dat[3,5] <- NA
names(dat) <- c(letters[1:4], 'fact')
ff <- a ~ b + fact
# This omits the row with a missing observation on the factor
model.matrix(ff, dat)
# This keeps the NA, but it gives me a data frame and does not dichotomize the factor
model.frame(ff, dat, na.action=NULL)
_
これが私が入手したいものです:
_ (Intercept) b fact2 fact3 fact4 fact5
1 1 0.7266086 0 0 0 0
2 1 -0.6088697 0 0 0 0
3 NA 0.4643360 NA NA NA NA
4 1 -1.1666248 1 0 0 0
5 1 -0.7577394 0 1 0 0
6 1 0.7266086 0 1 0 0
7 1 -0.6088697 0 0 1 0
8 1 0.4643360 0 0 1 0
9 1 -1.1666248 0 0 0 1
10 1 -0.7577394 0 0 0 1
_
行名に基づいて、_model.matrix
_オブジェクトを少しいじることができます。
_MM <- model.matrix(ff,dat)
MM <- MM[match(rownames(dat),rownames(MM)),]
MM[,"b"] <- dat$b
rownames(MM) <- rownames(dat)
_
これは:
_> MM
(Intercept) b fact2 fact3 fact4 fact5
1 1 0.9583010 0 0 0 0
2 1 0.3266986 0 0 0 0
3 NA 1.4992358 NA NA NA NA
4 1 1.2867461 1 0 0 0
5 1 0.5024700 0 1 0 0
6 1 0.9583010 0 1 0 0
7 1 0.3266986 0 0 1 0
8 1 1.4992358 0 0 1 0
9 1 1.2867461 0 0 0 1
10 1 0.5024700 0 0 0 1
_
または、contrasts()
を使用して作業を行うこともできます。手作業でマトリックスを作成すると、次のようになります。
_cont <- contrasts(dat$fact)[as.numeric(dat$fact),]
colnames(cont) <- paste("fact",colnames(cont),sep="")
out <- cbind(1,dat$b,cont)
out[is.na(dat$fact),1] <- NA
colnames(out)[1:2]<- c("Intercept","b")
rownames(out) <- rownames(dat)
_
これは:
_> out
Intercept b fact2 fact3 fact4 fact5
1 1 0.2534288 0 0 0 0
2 1 0.2697760 0 0 0 0
3 NA -0.8236879 NA NA NA NA
4 1 -0.6053445 1 0 0 0
5 1 0.4608907 0 1 0 0
6 1 0.2534288 0 1 0 0
7 1 0.2697760 0 0 1 0
8 1 -0.8236879 0 0 1 0
9 1 -0.6053445 0 0 0 1
10 1 0.4608907 0 0 0 1
_
いずれの場合も、両方のメソッドを、より複雑な数式を処理できる関数に組み込むことができます。私は練習問題を読者に任せます(紙で出会ったときにその文を嫌うのは何ですか;-))
Jorisの提案は機能しますが、これを行うためのより迅速でクリーンな方法は、グローバルなna.action設定を使用することです。 「合格」オプションは、元のデータセットからNAを保持するという目標を達成します。
結果の行列には、元のデータセットに対応する行にNAが含まれます。
_options(na.action='na.pass')
model.matrix(ff, dat)
_
結果の行列は、NAを含む行をスキップします。
_options(na.action='na.omit')
model.matrix(ff, dat)
_
元のデータにNAが含まれていると、エラーが発生します。
_options(na.action='na.fail')
model.matrix(ff, dat)
_
もちろん、グローバルオプションを変更するときは、コードの他の部分の動作を変更する可能性があるため、常に注意してください。注意深い人は、元の設定をcurrent.na.action <- options('na.action')
のようなもので保存し、model.matrixを作成した後にそれを元に戻す可能性があります。
もう1つの方法は、model.frame
の2番目の引数として引数na.action=na.pass
を指定してmodel.matrix
関数を使用することです。
> model.matrix(ff, model.frame(~ ., dat, na.action=na.pass))
(Intercept) b fact2 fact3 fact4 fact5
1 1 -1.3560754 0 0 0 0
2 1 2.5476965 0 0 0 0
3 1 0.4635628 NA NA NA NA
4 1 -0.2871379 1 0 0 0
5 1 2.2684958 0 1 0 0
6 1 -1.3560754 0 1 0 0
7 1 2.5476965 0 0 1 0
8 1 0.4635628 0 0 1 0
9 1 -0.2871379 0 0 0 1
10 1 2.2684958 0 0 0 1
model.frame
を使用すると、na.action
が呼び出されたときに維持されるmodel.matrix
に適切なアクションを設定できます。
mattdevlin と Nathan Gould の答えを見た後、私はもっと簡単な解決策に出くわしました。
model.matrix.lm(ff, dat, na.action = "na.pass")
model.matrix.default
はna.action
引数をサポートしていない可能性がありますが、model.matrix.lm
はサポートしています!
(Rstudioのオートコンプリートの提案からmodel.matrix.lm
を見つけました—他のライブラリを追加するライブラリをロードしていない場合、model.matrix
のデフォルト以外の唯一のメソッドのようです。それから私はそれがサポートするかもしれないと推測しましたna.action
引数。)