Scilab と R による 3D 散布図と回帰平面
井口豊(生物科学研究所,長野県岡谷市)
最終更新:2024 年 5 月 8 日
1. はじめに
久しぶりに Scilab を使ってみた。 R を使うことが多いため,うっかりすると,スクリプトを混同してしまうので,基本的な使い方を再確認する意味でも,たまには, Scilab を使うべきだと実感した。ここに書いた 3 次元グラフでは,私は gnuplot を使い発表することが多いし,最近もそうだった(井口,2019)。 Scilab の難点として, gnuplot に比べて,作図の時間も長めとなるからだ。
ここでは,3 次元データの散布図と,それに対する重回帰平面の適合について紹介する。このような作図は,よくありそうで,意外と無かった。ここで言う,重回帰平面とは,二変数 x, y を説明変数, z を目的変数とする回帰式が表す 3 次元平面である。
これを回帰直線と呼ぶ人がいるが,文字通り,回帰平面と呼ぶべきであり,それを Scilab で作図した例を示す。
2. Scilab による重回帰式フィット
Scilab による重回帰式のフィットには, reglin 関数を使う。 R で一般的に見られるように,各変数を明示的に入れるなら, Scilab でも以下のようなスクリプトになる。
reglin(x, y, z)
これでも計算されるのだが, Scilab の場合,回帰式を適切にフィットさせるためには, x, y は,ひとまとめにして行列データ X として扱われる。実際, reglin のオンラインマニュアルにも,そう書かれている。
reglin(X, z)
この点をまずチェックして見よう。大きさ 100 の標本で, x, y を正規乱数として, z を以下の式から算出する。
この x, y, z データを使って,逆に,回帰式を推定し,元の係数が復元されるかどうか調べるのである。
// スクリプト開始 n = 100; rand("seed", 10) x = rand(1, n, "normal"); y = rand(1, n, "normal"); z = 2*x - y + 3; // 最小2乗フィット // 明示的に x, y を与えた場合 [p, q, r] = reglin(x, y, z) // x, y を行列データとした場合 X = [x; y]; [A, c] = reglin(X, z) // スクリプト終了
結果は,以下のようになった。
明示的に x, y を与えた場合
p = - 0.0227378
q = - 0.1204544
r = 0.9328821
x, y を行列データとした場合
A = 2, - 1
c = 3
これで, Scilab による重回帰では x, y を行列データにするべきだと確認できた。その上で,改めて,この結果を 3 次元グラフとして描画して見る。
// スクリプト開始 n = 100; rand("seed", 10) x = rand(1, n, "normal"); y = rand(1, n, "normal"); z = 2*x - y + 3; // 最小2乗フィット X = [x; y]; [A, c] = reglin(X, z) // データ最大・最小確認 max(X, 'c') min(X, 'c') // 空間メッシュ [xx, yy] = meshgrid(-3:0.4:3, -3:0.4:3); // 重回帰式 zz = A(1)*xx + A(2)*yy + c; // 既存グラフのクリア clf() // 3次元散布図 scatter3d(x, y, z, "fill"); // 軸ラベル sz = 5 xlabel("X", "fontsize", sz); ylabel("Y", "fontsize", sz); zlabel("Z", "fontsize", sz); // 回帰平面 surf(xx, yy, zz, 'facecol','yellow','edgecol','red') // スクリプト終了
その結果,出力されたグラフが初期状態で,次の図 1 である。
グラフは,マウスの右クリックで,グルグルと自由に回転できる。例えば,回帰平面の垂直断面図は,次の図 2 のようになる。
データ点が,回帰平面上に分布していることが,一目瞭然である。
3. R による重回帰式フィット
R で似たような機能を持つ関数として, car パッケージの scatter3d 関数がある。それと rgl パッケージを使うと,以下のようなスクリプトになる。
## スクリプト開始 library(car) library(rgl) x<- rnorm(100) y<- rnorm(100) z<- 2*x - y + 3 par3d(cex=1.2) scatter3d( axis.col=c("black", "black", "black"), axis.scales=T, x=x, y=z, z=y, residuals=F, xlab="X", ylab="Y", zlab="Z" ) rgl.snapshot("r-scatter3d-regression.png", fmt="png") ## スクリプト終了
その結果,出力されたグラフが次の図 3 である。
3 次元回帰平面に関する限り, R のほうがオプションの指定が面倒だ。
参考文献
井口豊 (2019)
諏訪盆地西部における御岳第一テフラの高度分布
日本地理学会発表要旨集 96: 124(2019 年度日本地理学会秋季学術大会).