Rとウェブの融合(6)ーrglによる3次元グラフィックスー

多次元データや地形情報を可視化する際、2次元プロットだと情報の把握が困難な場合があります。 このような時は3次元グラフィックスを用いると効果的に可視化できます。 今回はRで簡単に3次元グラフィックスを作成する方法を紹介します。

静的な3次元プロット

Rで3次元プロットを作成するにはpersp()関数、scatterplot3dパッケージ、latticeパッケージなどを利用できます(図1)。

> # scatterplot3d による3次元プロット
> library(scatterplot3d)
> scatterplot3d(iris[, 1:3], pch = as.numeric(iris$Species))
>  
> # latticeを使った3次元プロット
> library(lattice)
> cloud(Petal.Length ~ Sepal.Length * Sepal.Width, data = iris, groups = Species)

図1: 静的な3次元プロット

3次元プロットの場合、色々な視点からプロットを眺めることで情報を効率的に把握できます。 これらの関数ではプロット作成時にパラメータによって視点を設定することは可能ですが、 見ている人が自由に視点を操作することはできません(「静的」とはインタラクティブに視点を操作できない、という意味です)。

rglパッケージ

rglパッケージでは、OpenGLベースの自由度の高い3次元グラフィックスの作成、及び作成した3次元プロットに対する視点移動やズームイン・ズームアウトといったインタラクティブな操作を行うことができます。 OpenGLは3Dコンピュータグラフィックスを扱うための仕様ですが、rglパッケージで3次元プロットを作成するだけならOpenGLの知識は不要です。 データを探索的に把握したいときなどは、静的な3次元プロットよりもrglパッケージの方が便利です。 まずはデモを動かして、どのような3次元プロットを作成できるのか見てみましょう。

> install.packages("rgl") # 必要なら
> library(rgl)
> demo(rgl)

ウィンドウが開いて3次元プロットが表示されます(図2)。ウィンドウ上をマウスでドラッグすると視点の移動が、ホイールスクロールによりズームイン・ズームアウトが可能です。

図2: rglのデモ(抜粋)

3次元散布図

rglパッケージでは目的に応じて3次元プロットを簡単に作成するための関数が提供されています。 plot3d()により3次元散布図を作成できます(図3)。ベースグラフィックスのplotと同じように色や点のサイズなどを指定することもできます。

> plot3d(mtcars[c("disp", "drat", "mpg")], col = rainbow(3)[factor(mtcars$cyl)])

planes3d()を使うとlm()による線形回帰で得られる回帰平面を追加できます。

> fit <- lm(mpg ~ disp + drat, mtcars)
> coefs <- coef(fit)
> planes3d(coefs[2], coefs[3], -1, coefs[1], col="blue", alpha=0.5)

ellipse3d()を使うと回帰係数の同時信頼区間を表示できます。

> plot3d(ellipse3d(fit, level = 0.95), aspect=TRUE)

図3: 3次元散布図

様々な3次元プロット

plot3d()ではtype引数でプロットの種類を指定できます。pは点(デフォルト)、sは球、lは線、hは垂直線を描画します(図4)。

> # ラインプロット
> T <- seq(0, 10*2*pi, len = 500)
> F <- seq(0.5, 2, len = 500)
> plot3d(cos(T)*F, sin(T)*F, seq(0, 1, len = 500), type = "l")
> 
> # 球+垂直線プロット
> x <- runif(50); y <- runif(50); z <- runif(50)
> plot3d(x, y, z, type = "s")
> plot3d(x, y, z, type = "h", add = TRUE)

persp3d()により曲面を可視化できます。 高さのある地形データや多次元確率変数のような2変数の関数を把握するのに便利です。 次の例では2次元正規分布の確率密度を可視化しています(図4)。

> x <- y <- seq(-3,3,length.out=100)
> xy <- as.matrix(expand.grid(x, y))
> z <- mvtnorm::dmvnorm(xy)
> persp3d(x, y, z, col = "gray")

図4: 様々な3次元プロット

アニメーション

rglパッケージでは視点を連続して移動することでアニメーション風にプロットを表示できます。 play3d()により表示、movie3d()により動画の保存が可能です。 これらの関数とspin3d()を組み合わせることで、ぐるぐるまわるアニメーションを簡単に作成できます。アニメーションを停止するにはエスケープキーを押して下さい。

> plot3d(mtcars[c("disp", "drat", "mpg")])
> play3d(spin3d(c(0, 0, 1), 15))

補助的な作図関数

rglパッケージでは3次元プロットの注釈やタイトル、軸などを設定するための関数も提供されています。 以下に重要な関数を抜粋します。詳細は?関数名としてヘルプファイルを参照して下さい。

関数名 説明
par3d 様々なパラメータの指定
aspect3d アスペクト比の指定
axes3d 座標軸に関する一括設定
axis3d 座標軸の個別設定
open3d 描画デバイスを開く
close3d 描画デバイスを閉じる
decorate3d 座標軸やタイトルなどの一括指定
text3d テキスト注釈の追加
mtext3d テキスト注釈の追加
title3d タイトルの追加
bg3d 背景色の指定
grid3d グリッド線の追加
view3d 視点の移動

作成したプロットの保存

これまでの例では、R上で3次元プロットを表示していましたが、レポートなどを作成するために3次元プロットを画像で保存できます。 rgl.postscript()ではPDF、SVGなどのベクタフォーマットの画像に、 rgl.snapshot()ではPNG画像に保存できます。

なお、rglで続けてプロットを作成すると、たくさんのデバイスウィンドウが開きますが、 これらの画像出力関数ではアクティブな描画デバイスのプロットが保存されます(フォーカスのあるウィンドウではありません)。 rgl.dev.list()でデバイスのリストの取得、rgl.set()でアクティブなデバイスの変更が可能です。

WebGLの利用

WebGLとはウェブブラウザ上でOpenGLグラフィックスを扱うための仕組みです。 rglパッケージではwriteWebGL()関数によって3次元プロットをWebGLとして出力することができます。 HTMLファイルが作成されるので、これをウェブブラウザで開くことでインタラクティブな3次元プロットをブラウザ上で利用できるようになります。 但しWebGLのブラウザでの制約により、データ点が多すぎる場合(特にサーフェスプロットは点の数が膨大になるのでWebGLでは表示できない場合もあります)や視点移動のアニメーションなどの複雑な処理はサポートされていないことがあります。

> plot3d(mtcars[c("disp", "drat", "mpg")])
> writeWebGL()
> browseURL("webGL/index.html")

以上の操作によりwebGLフォルダの中にindex.htmlというファイルが作成されます。ブラウザ上でマウスを使って3次元プロットを操作してみてください。 なお、ブラウザによってはWebGLを再生するために設定が必要な場合があります。また出来るだけ最新のブラウザを使って下さい。 作成したHTMLファイルを別の環境で利用する場合は、webGLフォルダ内のCanvasMatrix.jssnapshot.pngというファイルもあわせて配布します。

knitrパッケージでのWebGLの利用

knitrパッケージやrmarkdownパッケージを使うとウェブレポートを作成することができます。 この中でインタラクティブに操作できる3次元プロットを表示することも可能です。 knitrrmarkdonwについては本誌2013年10月号、2014年11月号、『シリーズUseful R ドキュメント・プレゼンテーション生成』(共立出版)などを参考にして下さい。

以下にRマークダウンファイルの例を示します(k.Rmd)。

```{r include=FALSE}
library(rgl)
library(knitr)
knit_hooks$set(webgl = hook_webgl)
```

```{r results='asis', echo=FALSE}
writeLines(c('<script type="text/javascript">',
    readLines(system.file('WebGL', 'CanvasMatrix.js', package = 'rgl')), '</script>'))
```

# mtcarsの3次元プロット

```{r webgl=TRUE, echo=FALSE, fig.width=3, fig.height=3}
plot3d(mtcars[c("disp", "drat", "mpg")])
```

排気量、アクセル比、燃費の関係を可視化しました。

図5: knitrでのWebGLの利用例

今回紹介した3次元プロット作成関数以外にも、照光処理、行列による座標変換、マテリアル設定など、rglパッケージによりOpenGLの豊富な機能を使った高度な3Dグラフィックスを作成することができます。 今後はビッグデータ化により、扱うデータがより高次元で複雑なものになることが予想されます。3次元可視化を習得して、是非このような複雑なデータに対して効果的な可視化を実践して下さい。