多変量データの関係を何となく見る方法

多変量のデータがどんな関係を持っているか分からないとき、まずは生データを観察することで何となくデータの傾向が見えてくることがあります。いきなり主成分分析だとかをやってもよく分からないという場合は、統計処理をする前にデータ自体を眺めることでヒントが見えてきたりします。
たとえば、Rの組み込みデータセットの一つfgl

> fgl
       RI    Na   Mg   Al    Si    K    Ca   Ba   Fe  type
1    3.01 13.64 4.49 1.10 71.78 0.06  8.75 0.00 0.00  WinF
2   -0.39 13.89 3.60 1.36 72.73 0.48  7.83 0.00 0.00  WinF
3   -1.82 13.53 3.55 1.54 72.99 0.39  7.78 0.00 0.00  WinF
4   -0.34 13.21 3.69 1.29 72.61 0.57  8.22 0.00 0.00  WinF
5   -0.58 13.27 3.62 1.24 73.08 0.55  8.07 0.00 0.00  WinF
6   -2.04 12.79 3.61 1.62 72.97 0.64  8.07 0.00 0.26  WinF
7   -0.57 13.30 3.60 1.14 73.09 0.58  8.17 0.00 0.00  WinF
8   -0.44 13.15 3.61 1.05 73.24 0.57  8.24 0.00 0.00  WinF
9    1.18 14.04 3.58 1.37 72.08 0.56  8.30 0.00 0.00  WinF
10  -0.45 13.00 3.60 1.36 72.99 0.57  8.40 0.00 0.11  WinF
...

こんな感じのデータになっています。ガラス質の砂利(fragments)の成分データのよう。2〜9列目が各成分の構成比率となっています。

とりあえず各2成分の組み合わせを見る散布図行列を見てみると

pairs(fgl[,2:9]) #2~9列目の散布図行列


こんな感じになっています。散布図行列で傾向が分かることもありますが、3変数以上の関係を把握するのが難しく、また各散布図間で点がどういう対応関係にあるのかもわかりません。もちろん高次元データを直交座標に映して把握できれば良いわけですが、人間は3次元以上の空間は認識できないので、それは不可能です。それでも何とかしようということで、平行座標プロットというものが考えられています。
平行座標プロットとは、その名の通り、各変数軸(座標軸)を平行に並べたものです。直交は無理なので、平行に並べるわけです。これにより、ある程度多変数間の繋がりを視覚化することができます。

fglデータに対する平行座標プロットはこのようになります。Rでは、MASSライブラリを用いて

library(MASS)
parcoord(fgl[,2:9])

とすることで表示できます。簡単です。
これだけでも何となく傾向が分かると思いますが、線が重なってしまい(これは平行座標プロットでは仕方のないことですが)、目で見た傾向(Naが中程度のものはMgが大きくなる傾向があり…)が本当に正しいか不安です。傾向の違う線が途中で混ざっていても分からないからです。
そこで、平行座標プロットに色をつけることでもう少し分かりやすいものとすることを考えます。

# x:        列が変数、行がサンプルのデータ
# order.no: 列についてソートした上で色付けしたい場合は列番号を指定
# whiteRow: 表示しない行番号(ソート後)
# over:     下から描画したい場合(変数値の大きい側が上書き描画)はT
modParcoord <- function(x,order.no=-1,whiteRow=c(),over=F){
  #オーダーする変数が指定されている場合は並び変え
  if(order.no!=-1){
    x.order <- x[order(x[,order.no]),]
  }else{
    x.order <- x
  }
  #描画しない部分を用意
  if(!is.null(whiteRow)){
    x.white <- x.order[whiteRow,]
    x.draw <- x.order[-whiteRow,]
  }else{
    x.white <- NULL
    x.draw <- x.order
  }
  #残った部分を描画
  n.draw <- nrow(x)-length(whiteRow)
  col.alpha <- rep(1.0,n.draw) #半透明度 ここでは指定しない
  col.draw <- rainbow(n.draw,col.alpha)
  if(over){ #色順がそのままになるように描画順を逆転
    x.draw <- x.draw[order(x.draw[,order.no],decreasing=T),]
    col.draw <- rev(col.draw)
  }
  x.draw <- rbind(x.white,x.draw) #描画しない部分(white)を先に描画
  parcoord(x.draw,col=c(rep("white",length(whiteRow)),col.draw))
}

このような関数を用意して、色(グラデーション)つきの平行座標プロットを書いてみたものが次のグラフです。Caの列でソートして値順に色をつけています。

modParcoord(fgl[,2:9],6,over=T)


真ん中あたりのオレンジや黄色、緑といった線の集まりが特に傾向を持っていることが見てとれます。色なしのparcoordに比べ、傾向把握がより信頼できるものになったことが分かるかと思います。
また、modParcoord関数にはoverという引数を持たせています。これは「線を下から書くか上から書くか」を指定する引数です。parcoord関数は行の上から順に線を描いていき、後から書いた線は前の線を塗りつぶす形で描画されます。そのため先に書かれた変数の傾向が見えなくなるという問題を緩和するために、描画の順番を逆転できるようにしています。先ほどのグラフで逆転してみると

となり、かなり見え方が違ってきます。

さて、めでたく生データの傾向が見えたわけですが、実は最初に示した通り、fglデータは右端にカテゴリー変数が付加されています。データ収集者が予めカテゴライズしてくれたものです。この中で、"WinNF"カテゴリだけをプロットしてみると

となります(ここでは色をつける意味はありませんが、modParcoord関数を流用しえいるためこのようになっています)。これは先ほど見つけた「オレンジや黄色、緑」の傾向とほとんど同じものです。目視による分析が正しく傾向を見つけられていたことが裏付けられると言えます。
実際のデータではこのような適切なカテゴリ変数が与えられていないことも多いでしょう。クラスタリングや次元縮約などの方法でカテゴリを見つけていくことになるわけですが、その前に、生データを色々な角度から見ることで、結果の当たりをつけることができる場合もあるということが実感できるのではと思います。