3次元のデータをグラフにする
3次元のベクトルで表されるデータをグラフ化する方法について,いくつかまとめてみました.
使用するデータ
volcano
Rに組み込まれているデータセットで,Maunga Whau山の標高データだそうです.10m * 10mのグリッドで,87rowと61columnからなります.rowは東から西へ,columnは南から北へのラインと対応しており,最小値は94,最大値は195です.まずはデータセットの準備.
# あらわしたいデータのラベルを作成 EastWest <- 1:nrow(volcano) * 10 # rowの数は87 SouthNorth <- 1:ncol(volcano) * 10 # columnの数は61 # 頂上の位置を変数に入れておく mountaintop <- which(volcano == max(volcano), arr.ind = TRUE) * 10
グラフを描く
image
値に応じた色を格子上に示す関数です.
主要な引数は以下のとおり.
x, y: プロットされるzの位置を表す座標.昇順でなければならない.
z: プロットされる値のmatrix.NA値も許される.
col: プロットされる値につける色.
備考
xはnrow(z)+1かnrow(z)と等しくなる必要がある.前者ならセルの境界に,後者ならセルのmidpointに,値がプロットされる.
NA値は透明になる.
zのmatrixはf(x[i], y[i])のtableとして解釈される.よって,xはrowの数に,yはcolumnの数に,対応している必要がある.つまり,データセットとグラフは90度回転した関係にあるということですね.
実例
image(EastWest, SouthNorth, volcano, col = heat.colors(100)) # col の値には他にこんなのもあります. # rainbow(7), heat.colors(10), topo.colors(100), terrain.colors(100), gray((0:100)/100), gray((100:0)/100) # つづけて頂上の位置にプロットを置きます points(mountaintop[1], mountaintop[2], pch = 20, col = "blue") # 等高線を描くcontour関数も合成してみましょう.今回は標高175mの位置に. contour(EastWest, SouthNorth, volcano, levels = 175, add = TRUE) # levels = seq(90, 200, by = 5) などもできます.
persp
x-y平面に遠近図を描く関数です.主要な引数
x, y: プロットされるzの位置を表す座標.昇順でなければならない.
z: プロットされる値のmatrix.NA値も許される.
col: プロットされる値につける色.
theta, phi: 視座の角度.前者は横向きの回転,後者は縦向きの回転.
r: 視野とプロットの距離.
d: 遠近感の強さ.1以上なら遠近感が弱まり,1以下なら強調される.
scale: FALSEなら,全軸共通のスケーリングがなされる.
border: 表面に描かれる線の色.NAなら線を描かない.
ltheta, lphi: 指定した値の視座から光が投影されたような陰がつく.
shade: 陰がつく.1に近いほど濃い陰になる.
ticktype: "detailed"なら軸にスケールがプロットされる.デフォルトでは"simple".
nticks: スケールの数を指定.
実例
ここでは特に,2次元のグラフに使われる関数を3次元のグラフに描くtrans3d関数を使って,点や線も追加してみます.
mtMaugnaWau <- persp(EastWest, SouthNorth, volcano, theta = 25, phi = 30, scale = FALSE, col = "green", border = NA, ltheta = 120, shade = 0.7, ticktype = "detailed", cex.axis = 0.8) # 頂上の追加 points(trans3d(mountaintop[1], mountaintop[2], max(volcano), pmat = mtMaugnaWau), col = "red", pch = 16) # 頂上から標高150mラインにある一点に直線を引く level150 <- which(volcano == 150, arr.ind = TRUE) * 10 x <- 6 # 150mラインのうちのどの点に直線を引くか.適当に決めて6にしました. lines(trans3d(c(mountaintop[1], level150[x, 1]), c(mountaintop[2], level150[x, 2]), c(max(volcano), 150), pmat = mtMaugnaWau), col = "blue")
scatterplot3d
値を3次元にプロットする関数です.CRANからパッケージのダウンロードが必要です.scatterplot3d: 3D Scatter Plot
主要な引数
x, y, x: それぞれの座標.
scale.y: y軸のスケール (奥行き) の調節.
angle: x-y軸の角度
highlight.3d: TRUEなら,y軸の値に応じて色の濃さが変わる.
実例
# データセットの準備. EastWest3d <- rep(EastWest, length(SouthNorth)) SouthNorth3d <- vector(length = 87 * 61) for(i in 1:61){ SouthNorth3d[((i - 1) * 87 + 1):(i * 87)] <- SouthNorth[i] } # プロットの実行. library(scatterplot3d) # パッケージの呼び出し. mtMaugnaWau3d <- scatterplot3d(EastWest3d, SouthNorth3d, volcano, scale.y = 0.5, highlight.3d = TRUE) # plane3dメソッドやpoints3dメソッドで平面や点の追加が可能です. # 標高150mラインに平面の追加. mtMaugnaWau3d$plane3d(150, x.coef = 0, y.coef = 0, lty.box = "dashed") # 頂上の追加. mtMaugnaWau3d$points3d(mountaintop[1], mountaintop[2], max(volcano), col = "blue", pch = 19)
どんなときに使うか
まず,連続的な値をべたーっと面で描きたいときには,imageやperspが適しているでしょう.imageは直感的にイメージがつかみにくいですが,全体が見渡せるので,ひとつひとつの値をある程度きちんと検証できます.一方,perspは直感的にイメージがつかめますが,山や谷で見えなくなる部分があり,データをすべて見せきれないかもしれません.次に,線・点など,面に比べるととびとびになる値を3次元にプロットしたいときは,scatterplot3d関数が適しているでしょう.引数も充実しており,ラベルやスケールなどもきちんと描くことができます.
※ 他にもこんな関数がある,などご存じでしたら,ぜひトラックバックなどでお教えいただければ幸いです!