FCMPプロシジャはユーザー定義関数を作成するだけでなく、簡単な行列計算をしたい場合にも便利です。
簡単なサンプルとして、以下の連立方程式をFCMPプロシジャによる行列計算で求めてみたいと思います。
ちなみに行列で解を求める式はこんな感じでしょうか。
まずは式の数字部分をデータセット化しておきます。
data DT1;
input A B C D;
cards;
1 1 1 6
2 4 3 19
5 3 2 17
;
run;
1 | 1 | 1 | 6 |
2 | 4 | 3 | 19 |
5 | 3 | 2 | 17 |
|
FCMPプロシジャで行列により解を求めます。
proc fcmp;
*** ① 計算用の配列を定義 ;
array _ABC [3, 3] / nosym;
array _D [3, 1] / nosym;
array _INV [3, 3] / nosym;
array _OUT [3] / nosym;
*** ② 計算するデータセットを配列に格納 ;
rc = read_array("DT1", _ABC, "A","B","C");
rc = read_array("DT1", _D , "D");
*** ③ 行列計算して解を出す ;
call inv(_ABC, _INV); * 逆行列 ;
call mult(_INV, _D, _OUT); * 行列の積 ;
*** ④ 結果をデータセットに書き出す ;
rc = write_array("OUT1", _OUT, "RESULT") ;
run;
データセットOUT1
x=1, y=2, z=3 という結果が得られました。 |
解説
処理のおおまかな流れは、計算用のデータセットを配列に格納 → その配列を使って行列計算 → 出た解をデータセットに吐き出す。。といった感じです。
①まず行列計算で必要になる配列を定義しておきます。
NOSYMをつけると配列に変数を割り当てる必要がなくなります。
(DATAステップのARRAYでいうところの一時配列_
TEMPORARY_みたいなもの)
②
READ_ARRAY関数でデータセットDT1を配列に格納します。
READ_ARRAY("読み込むデータセット", "読み込んだデータを格納する配列", "読み込む変数1", "読み込む変数2"…) |
③読み込んだ配列に対して、行列計算して解を出します。
逆行列 … CALL INV( 配列, 結果を格納する配列 )
行列の積 … CALL MULT( 配列1, 配列2, 結果を格納する配列 )
|
④
WRITE_ARRAY'関数で解をデータセットOUT1に格納します。
WRITE_ARRAY("出力後データセット名", "出力する配列", "出力時の変数名1", "出力時の変数名2"…) |