カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

Rの2つのパッケージ――mixOmicsとcaretのplsda関数の比較

2020年4月21日追記

現在はmixOmicsはBioconductorに組み込まれています。mixOmicsの読み込みは次のコードで置き換えてください。

if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

BiocManager::install("mixOmics")

本文

RでPLS-DAを提供するパッケージとしてmixOmicsとcaretをしばしば使います。この2つのパッケージが提供する2つのplsda(mixOmics::plsdaとcaret::plsda)、これまで何が違うのか漠然としか把握していなかったのですが、現行バージョン(mixOmics 5.0-1 2012-12-11, caret 5.17-7 2013-08-04)ではずいぶん大きな違いがありました。具体的にはscale関数によるx, yの標準化の有無です。

caretは与えられたxとyをそのまま使うのに対して、mixOmicsは内部でxとyに対してscale(center=TRUE, scale=TRUE)を呼び出します。つまるところ、何も考えず或いは短いコードで済ませるのであればmixOmics::plsdaが適していますし、標準化を自前で行いたいのであればcaret::plsdaが適しているのかもしれません。

小さな違いですが、統計で使う上ではそれなりに大きな違いを生み出してしまうので注意です。

ドキュメントもソースコードもしっかり読んだわけではないので、間違いやより詳細な違いなどありましたが、ご指摘頂けると幸いです。

サンプルコード

具体的な違いは以下のコードで確かめることができます。

require(mixOmics)
require(caret)

caret.iris.plsda.raw       <- caret::plsda(iris[,1:4], iris[,5])
caret.iris.plsda.scaled    <- caret::plsda(scale(iris[,1:4]), iris[,5])
mixOmics.iris.plsda.raw    <- mixOmics::plsda(iris[,1:4], iris[,5])
mixOmics.iris.plsda.scaled <- mixOmics::plsda(scale(iris[,1:4]), iris[,5])

sum(caret.iris.plsda.raw$scores == caret.iris.plsda.scaled$scores)
#=> 0
sum(mixOmics.iris.plsda.raw$variates$X == mixOmics.iris.plsda.scaled$variates$X)
#=> 51

require(car)

par(mfrow=c(2,2))
dataEllipse(caret.iris.plsda.raw$scores[,1:2], groups=iris$Species, main="caret.plsda.raw", lty=3, lwd=1, fill=TRUE, levels=0.99)
dataEllipse(caret.iris.plsda.scaled$scores[,1:2], groups=iris$Species, main="caret.plsda.scaled", lty=3, lwd=1, fill=TRUE, levels=0.99)
dataEllipse(mixOmics.iris.plsda.raw$variates$X[,1:2], groups=iris$Species, main="mixOmics.plsda.raw", lty=3, lwd=1, fill=TRUE, levels=0.99)
dataEllipse(mixOmics.iris.plsda.scaled$variates$X[,1:2], groups=iris$Species, main="mixOmics.plsda.scaled", lty=3, lwd=1, fill=TRUE, levels=0.99)

無題.png

本当であればcaretとmixOmicsのscaleしていない群同士(raw)とscaleした群同士(scaled)が同じ形となるはずですが、どう見てもcaretのrawだけ異なっていることが上図で示されていると思います。