4.4K Views
March 26, 24
スライド概要
[第9回大阪SAS勉強会] 森岡裕
SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです
SASのコールルーチンは57個あるねん. 10分で全部説明するねん 森岡 裕
CALLルーチンの定義 CALLルーチンは変数値を変更したり、その他のシステム関数を実行したりします。CALLルーチンは関 数に似ていますが、割り当てステートメントや式の中で使用できない点で関数と異なります。 すべてのSAS CALLルーチンは、CALLステートメントで呼び出されます。つまり、CALLステートメン ト内のキーワードCALLの後でルーチン名を指定する必要があります。 SASの公式の説明. 要は指定された引数そのものに作用したり,戻り値のない動作をするもの. 2024/1/30時点で,57個のコールルーチンが公式リファレンスで確認されたので,それらを全て解説します. もう二度とやりたくないぐらい面倒な資料作成でした!
【No1】 CALL ALLCOMB ルーチン
CALL ALLCOMB(count, k, variable-1, ..., variable-n);
nCr n個の変数値から一度にr個の変数値を取得する場合のすべての組み合わせを変化量の小さい順に生成し
ます.呼び出されるタブに次のパターンを出すが,組み合わせができった後は同じ組み合わせを返し続けるので
ループ終端にcomb関数で,組み合わせ数を設定することが多い
data A;
array ar{5} $2 ("A","B","C","D","E");
n=dim(ar);
k=3;
ncomb=comb(n, k);
do j=1 to ncomb;
call allcomb(j, k, of ar[*]);
output;
end;
run;
%syscall
を使ってマクロコードで動かした場合,&sysinfoに収束状態(-1で完全収束)が入るオマケあり
注意点 対象変数の上限が33個 それを超える場合はCALL ALLCOMBIルーチンが必要
【No2】 CALL ALLCOMBI ルーチン
CALL ALLCOMBI(N, K, index-1, …, index-K, <, index-added, index-removed>);
n個のオブジェクトを同時にk個使用するときのインデックスのすべての組み合わせを、変化量の小さい順に生成し
ます。 nCr なのはCALL ALLCOMB ルーチンと同じだけど,インデックスのみで処理する!なので数値変数しか対
象にとれない!!どの変数を足して,どの変数を落として,組み合わせを変化させてるかっていう挙動をインデッ
クスで返せるところが嬉しい
data A;
array ar{5} $2 ("A","B","C","D","E");
array i[3];
array rtr[3] $2;
n=dim(ar);
k=3;
ncomb=comb(n, k);
do j=1 to ncomb;
call allcombi(5, 3, of i{*} ,add,remove);
do h=1 to k;
rtr[h]=ar[ i[h] ];
end;
output;
end;
run;
【No3】CALl ALLPERMルーチン ! 順列(を生成するルーチン.複数の変数の値のすべての順列を変化量の小さい順に生成 FACT関数で階乗を求めて,そこまでループさせるのが一般的 data wk1; array x [4] $ ("A","B","C","D"); n=dim(x); nfact=fact(n); do i=1 to nfact; call allperm(i, of x[*]); output; end; run;
【No4】 CALL CATS ルーチン call cats( [結果を入れたい変数] ,[対象1],[対象2]..... ) data wk1; length y $20.; x1="A"; x2="B"; x3="C"; call cats(y,of x1-x3); run; y = cats(of x1-x3); と同義 じゃあ なんでわざわざコールルーチンにすんねんという話 data wk1; length y $20.; do i= 1 to 20; if mod(i,3) =0 then call cats(y , i,"|"); end; このように,ループの中で,結果をも求めたい変数に何度も処理を書ける場合 run; y=cats(y , i,"|"); という冗長を防ぐことができる
【No5】 CALL CATT ルーチン 【No4】 CALL CATS ルーチン と同じ.CATS関数とCATT関数の違いなだけ,両方TRIMは入るけど,LEFTが 入るのがCATSだけ data wk1; length y $20.; call catt(y, " run; A",2," B"); これがCATSルーチンだと data wk1; length y $20.; call cats(y, " run; A",2," B");
【No6】 CALL CATX ルーチン call catx(区切り文字, [結果を入れたい変数] ,[対象1],[対象2]..... ) 第一引数が,結果を返すじゃなくて,区切り文字ってことに注意 data wk1; length y $20.; call catx("@", y, 1,2,3); run;
【No7】CALL COMPCOSTルーチン COMPGED関数で,AとBの文字列を比較して,Bにどういった操作を加えるとAになるかってコスト計算の観点から デフォルトでコスト点数がCOMPGED関数内に設定されている 一個文字を足すだけで一致するなら 20コスト 一文字の入れ替えで一致するなら200コスト みたいな感じね
その点数表 そのものを改変できるのがCALL COMPCOSTルーチン data wk2; length target x $20.; if _n_ = 1 then call compcost( 'insert=', 1, 'replace=', 3); target = "APPLE"; do x="AAPPLE","BPPLE","APPLE"; GED=compged(x, target); output; end; run; これによってルールが改変され 一個文字を足すだけで一致するなら 1コスト 一文字の入れ替えで一致するなら3コスト
【No8】CALL EXECUTEルーチン データステップ中にCALl EXECUTEで実行された文字列が,データステップ中終了後にコードとして実行される 動的な値を組み合わせたりして,メタプログラミングができる. data _null_; call execute("data A;"); if ranuni(777) <0.5 then do; call execute("set sashelp.iris;"); end; else do; call execute("set sashelp.class;"); end; call execute("run;"); run; 50%の確率でirisかclassがセットされる謎の処理コードを生成する
【No9】CALL GRAYCODE ルーチン グレイコード(交番二進符号)を生成する.(グレイコードが何かはググってくださいませ). 2進数の表現で、隣 り合う値でビットの変化が1ビットしかないように変化していくものです.電子回路とかでも使われる data A0; array N{3}; do i = 1 to 2**dim(N); call graycode (-1, of N{*}); output; end; run;
【No10】CALL IS8601_CONVERTルーチン ISO 8601規格の間隔を日時値とデュレーション値に変換します。または、日時値とデュレーション値をISO 8601 規格の間隔に変換します。 data _null_ ; length ans $20. ; format ans $n8601e. ; call is8601_convert('dt/dt' , 'du' ,"2023-01-01" ,"2023-02-05" , ans ) ; putlog ans = ; run ; 2つの日付の間隔は P1M4D つまり 一か月と4日後わかる 逆に区間を指定して,始点や終点を求めるなどの多様な使い方ができるルーチン
【No11】CALL LABELルーチン call label( [こっちに指定した変数のラベルを] ,[こっちの変数に値として戻す]) 引き数が2つに固定されていて,Aの変数のラベル情報をBに入れるというコールルーチンなので data wk1; length var $100.; set sashelp.class; array ch _character_; array num _numeric_; do over ch; call label(ch,var); if ch ne "var" then end; do over num; call label(num,var); output; end; stop; run; output;
【No12】CALL LEXCOMBルーチン n個の変数を同時にk個使用するときの、重複しない非欠損値のすべての組み合わせを辞書式順序で生成 LEXは lexicographic(辞書式順序) 【No1】 CALL ALLCOMB ルーチンとほぼ同じ,違いは重複を除くことと辞書順であること(ALLの方は変化量順) つまりALLCOMBだと data A; array ar{5} $2 ("A","A","C","D","E"); n=dim(ar); k=3; ncomb=comb(n, k); do j=1 to ncomb; call allcomb(j, k, of ar[*]); output; end; run; 5C3の時に 3ペアの重複が生じるが
CALL LEXCOMBルーチンだと ただし,重複がある場合の組み合わせ数の計算は非常に複雑であり,関数もない.よってループ終端条件を多 めに設定せざるをえない. 組み合わせを出し切った以降のコールは_ERROR_=1を返すのでそれを利用して処理する
【No13】CALL LEXCOMBIルーチン 【No2】 CALL ALLCOMBI ルーチンとの違いは<, index-added, index-removed>がないことと 変化量ではなく 辞書式順序で生成する点 data _null_; array x[5] $3 ('ant' 'bee' 'cat' 'dog' 'ewe'); array c[3] $3; array i[3]; n=dim(x); k=dim(i); i[1]=0; ncomb=comb(n, k); do j=1 to ncomb; call allcombi(n, k, of i[*]); do h=1 to k; c[h]=x[i[h]]; end; put @4 j= @10 'i= ' i[*] +3 'c= ' c[*]; end; run; data _null_; array x[5] $3 ('ant' 'bee' 'cat' 'dog' 'ewe'); array c[3] $3; array i[3]; n=dim(x); k=dim(i); i[1]=0; ncomb=comb(n, k); do j=1 to ncomb; call lexcombi(n, k, of i[*]); do h=1 to k; c[h]=x[i[h]]; end; put @4 j= @10 'i= ' i[*] +3 'c= ' c[*]; end; run; 下段の方が 辞書式に生成されていることがわかる
【No14】CALL LEXPERKルーチン n個の変数から一度にk個を取り出した非欠損値の重複しないすべての順列を辞書式順序で生成します。 ALLPERMはk個ではなく全部の順列なので,そこが違う 4個の変数から一度に2個だしたときの順列は data wk1; array x [4] $ ("A","B","C","D"); n=dim(x); k=2; nperm=perm(n, k); do i=1 to nperm; call lexperk(i,k, of x[*]); output; end; run; 12種類.ループ終端はperm関数を使う
【No15】CALL LEXPERMルーチン 複数の変数の非欠損値の重複しないすべての順列を辞書式順序で生成します 【No3】CALl ALLPERMルーチンは 欠測値でもつくれる data _null_; array x[4] $3 ('' 'B' 'C' 'D'); n=dim(x); nfact=fact(n); do i=1 to nfact; call allperm(i, of x[*]); put i 5. +2 x[*]; end; run; CALL LEXPERMルーチンは非欠損値のみなので無理 あとは生成順が,辞書的で,allと異なる
【No16】CALL LOGISTICルーチン ロジスティック関数 を全引数に適応する data _null_; x1=1; x2=2; x3=3; y1=-1; y2=-2; y3=-3; call logistic(of x: y:); put (_all_) (/=); run; 正負たすと1になります
【No17】CALL MISSINGルーチン 欠損値を割り当てる.対象に文字変数,数値変数を混在で持つことができる data a; set sashelp.iris; call missing(of Species SepalWidth); run; 通常なら変数の初期化WARNINGが起きてしまう場合に,初期化をするためにもよく使われる data b; length x 8. y $10.; run; data b; length x 8. y $10.; call missing(of x y); run; SDTMとかADaMでattribをマクロ 化して,初期段階で定義を整える場 合,後半のステップで確定するであ ろうAVISITとかBASEとかCHGは, 初発の段階で,初期化エラーがで ちゃいがちなので,そういうときに call missing(of BASE CHG AVISIT AVISITN......)的なのはよく見ますね
【No18】CALL MODULEルーチン ★未検証★ 外部モジュールを実行する.SASCBTBLっていう定義カタログを作って,それを 介したりするみたい… DLLとか.たとえばWindowsプラットフォームでのKERNEL32ダイナミックリン クライブラリのWin32 APIをたたいてビープ音を出す例などは以下のようになるら しい(SASサーバが音でないので,うまくいってるか不明) filename sascbtbl temp; data _null_; file sascbtbl; input; put _infile_; datalines4; routine Beep minarg=2 maxarg=2 stackpop=called callseq=byvalue module=kernel32; arg 1 num format=pib4.; arg 2 num format=pib4.; ;;;; data _null_; call module("Beep", 1380, 1000); run;
【No19】CALL POKEルーチン ★未検証★ 試すな!キケン!! 32ビットプラットフォームのメモリに値を直接書き込みます。 メモリに直書きするヤバイやつ,公式リファレンスにも,素人が使ったら, コンピューターごと破損されるよーとか言ってるので使わない.試しもしてない.
【No20】CALL POKELONGルーチン ★未検証★ 試すな!キケン!! 32ビットおよび64ビットのプラットフォームのメモリに値を直接書き込みます。 これもメモリに直書きするヤバイやつ,公式リファレンスにも,素人が使ったら,コンピューターごと破損 されるよーとか言ってるので使わない.試しもしてない. さすがに私も触らない
【No21】CALL PRXCHANGEルーチン 正規表現系のコールルーチン.パターンマッチングの置換を担う.PRXCHANGE関数と同様. ターゲットが引数=戻りってだけ, data a ; name="Morioka, Yutaka"; PRE = prxparse('s/(¥w+), (¥w+)/$2, $1/'); call prxchange(PRE, -1, name); run ;
【No22】CALL PRXDEBUGルーチン 正規表現のデバックのためのルーチン. call prxdebug(1); でデバックモードがONになり call prxdebug(0);でOFFになる.ONになっている状態で 正規表現が含まれるコードの実行が起きると,解析結果がログに表示される data a ; call prxdebug(1); name="Morioka, Yutaka"; PRE = prxparse('s/(¥w+), (¥w+)/$2, $1/‘); call prxchange(PRE, -1, name); call prxdebug(0); run ; どういう風に,どういう順番で処理されたかが,でるので, 正規表現がうまく行かない場合などに,見れば解決のヒン トがえられることが多い
【No23】CALL PRXFREEルーチン PRXPARSE関数によって,正規表現に割り当てられたメモリをリリースする,要するに消すってこと. data a ; name="Morioka, Yutaka"; PRE = prxparse('s/(¥w+), (¥w+)/$2, $1/'); call prxfree(PRE); call prxchange(PRE, -1, name); run ; PRXPARSE関数で割り当てたあと,CALL PRXCHANGEで使用する前に CALL PRXFREEで消しちゃってるので 正規表現がありませんってなってる.この挙動からCALL PRXFREEで,正規表現がメモリ解放されたことがわかる
【No24】CALL PRXNEXTルーチン
1つの文字列からパターン一致する箇所全てを抽出する場合はPRXNEXTルーチンと do whileループを組み
合わせる
data wk1;
length text found $20.;
text ="cathatbutgot";
ExpressionID = prxparse('/[a-z]at/');
start = 1;
stop = length(text);
call prxnext(ExpressionID, start, stop, text, position, length);
do while (position > 0);
found = substr(text, position, length);
output;
call prxnext(ExpressionID, start, stop, text, position, length);
end;
run;
【No25】CALL PRXPOSNルーチン PRXMATCH, PRXCHANGE, PRXSUBSTR, PRXNEXTのいずれかの結果を使用 して正規表現で指定されたキャプ チャバッファの位置と長さを返す. ⇒PRXPOSN単体で使用しても,キャプチャバッファが事前に他の関数やコール ルーチンで作られていなければ, 返すものがないため期待する結果は得られない 正規表現系コールルーチン.PRXPOSN関数と働きは似ているがCALL PRXPOSNはキャプチャバッファ自体では なくキャプチャバッファの位置と長さを返す点が異なる. data _null_; name="Yutaka, Morioka"; re=prxparse('/(¥w+), (¥w+)/'); if prxmatch(re, name) then do; call prxposn(re, 1, position, length); first = substr(name, position, length); put name= position= length= first= re= ; end; run;
【No26】CALL PRXSUBSTRルーチン 正規表現系.パターンに一致する部分文字列の位置と長さを返します。 data _null_; name="Yutaka, Morioka"; re=prxparse('/(¥w+), (¥w+)/'); call prxsubstr(re, name, position, length); put position= length=; run; CALL PRXPOSNルーチンはキャッチバッファ の情報をとるが,こちらは,マッチングした部 分文字列そのものの情報をだす
【No27】CALL RANBINルーチン 二項分布からランダム変量を返す CALL RANBIN(seed, n, p, x); nは試行回数 pはベルヌーイ試行の成功率 0 <p <1 100回のコイントスをやった場合に表がでる回数,それを5セット data wk1; seed=2023; do i=1 to 5; call ranbin(seed, 100, 0.5 ,x); output; end; run; シードストリーム シードは初期シードからルーチン実行 のたびに遷移する
【No28】CALL RANCAUルーチン コーシー分布からランダム変量を取り出す コーシー分布は,期待値が定義できず,正規分布より減衰が遅い,裾の厚い分布とか,特殊なやつですね data wk1; seed=2023; do i=1 to 500; data wk1; call rancau(seed, x); seed=45; output; do i=1 to 5; end; call rancau(seed, x); run; output; proc sgplot data=wk1; end; histogram x; run; run;
【No29】CALL RANCOMBルーチン 引数の値を置換し、n個の値のうちk個のランダムな組み合わせを返す data wk1; array AR $ x1-x5 ("A " "B" "C" "D" "E"); seed=1215; do i=1 to 10; call rancomb(seed, 3, of AR{*}); output; end; run; 5つの中から3個ランダムに選ぶ
【No30】CALL RANEXPルーチン 指数分布からランダム変量を返します data wk1; seed=2023; do i=1 to 5; call ranexp(seed, x); output; end; run; ランダムな事象の発生間隔を表す分布 data wk1; seed=2023; do i=1 to 10000; call ranexp(seed, x); output; end; run; proc sgplot data=wk1; histogram x; run;
【No31】CALL RANGAMルーチン ガンマ分布からランダム変量を返します。 ガンマ分布はある期間ごとに平均して1回起こる現象が1回起きるまでの期間が従う分布, call rangam(seed, [形状パラメータ], [戻り値]); data wk1; seed=2023; do i=1 to 5; call rangam(seed, 1,x); output; end; run; 指数分布の一般化 ちなみにガンマ分布とカイ二乗分布はつながってるという が,本当かしら data wk1; seed=2023; do i=1 to 5000; call rangam(seed, 2,x); output; end; run; proc sgplot data=wk1; histogram x; run; data wk2; do i=1 to 5000; x=RAND('CHISQUARE', 4); output; end; run; proc sgplot data=wk2; histogram x; run;
【No32】CALL RANNORルーチン 正規分布からランダム変量を返します data wk1; seed=2023; do i=1 to 5; call rannor(seed,x); output; end; run; data wk1; seed=2023; do i=1 to 10000; call rannor(seed,x); output; end; run; proc sgplot data=wk1; histogram x; run;
【No33】CALL RANPERKルーチン 引数の値を置換し、n個の値のうちk個のランダムな順列を返す data wk1; array AR $ x1-x5 ("A " "B" "C" "D" "E"); seed=1215; do i=1 to 10; call ranperk(seed, 3, of AR{*}); output; end; run;
【No34】CALL RANPERMルーチン
引数の値をランダムに置換します
.【No33】CALL RANPERKルーチンでn=k,つまり全部を対象にするのと同じこと
data wk1;
array AR $ x1-x5 ("A " "B" "C" "D" "E");
seed=1215;
do i=1 to 10;
call ranperm(seed, of AR{*});
output;
end;
run;
【No35】CALL RANPOIルーチン Poisson分布からランダム変量を返す ポアソン分布とは平均してλ回ランダムに起こる事象が、単位時間にちょうどk回起きる確率の分布ってことで CALL RANPOI(seed, [平均何回起こるであろうパラメータ], [戻り値]); data wk1; data wk1; seed=2023; seed=2023; do i=1 to 5000; do i=1 to 5; call ranpoi(seed,10,x); call ranpoi(seed,10,x); output; output; end; end; run; run; proc sgplot data=wk1; histogram x; run;
【No36】CALL RANTBLルーチン テーブル形式の確率分布からランダム変量を返す 最初の引数がシードで,最後が戻り値,真ん中は数値リストは,その位置の数字が生成される確率 data wk1; data wk1; seed=2023; seed=2023; do i=1 to 10000; do i=1 to 5; call rantbl(seed,0.2 ,0.1, 0.3, 0.1,0.3, x); call rantbl(seed,0.2 ,0.1, 0.3, 0.1,0.3, x); output; output; end; end; run; proc sgplot data=wk1; run; histogram x; run;
【No37】CALL RANTRIルーチン 三角分布からランダム変量を返します 三角分布ってのは,とりうる最小,最大の範囲を三角系の底辺として,最頻値の上に頂点がくる形の分布 CALL RANTRI(seed, [h:モーダル値], x); data wk1; パラメータhを使用した間隔(0,1)の三角分布から生成される変量xを返す seed=2023; data wk1; do i=1 to 100000; seed=2023; call rantri(seed,0.3,x); do i=1 to 5; output; call rantri(seed,0.3,x); end; output; run; end; proc sgplot data=wk1; run; histogram x; run;
【No38】CALL RANUNIルーチン 一様分布からランダム変量を返す data wk1; seed=2023; do i=1 to 5; call ranuni(seed,x); output; end; run; data wk1; seed=2023; do i=1 to 1000000; call ranuni(seed,x); output; end; run; proc sgplot data=wk1; histogram x; run;
【No39】CALL SCANルーチン 文字列からn 番目の単語の位置と長さを返す CALL SCAN(対象文字, n番目, 検出されたposition, 検出されたlength , "区切りのリスト" ,オプション修飾子); 第二引数は負にすると逆方向から走査する.オプション修飾子で,細かい挙動を指定できる data wk1; x="aa/rr/raeaeaa/d/aaaa/bb"; do i=1 to count(x,"/")+1; call scan(x, i, position, length,"/"); if not position then leave; Name=substrn(x, position, length); output; end; run; proc print data=wk1; run;
【No40】CALL SETルーチン SCL関数(データステップ中に他のデータセットにダイレクトアクセスしたり操作できる系)と組み合わせるの に必須のルーチン.ハッシュオブジェクトが実装されてからはSCL関数の出番は少なくなったけど. open関数で,データセットをホールドした後にCALL SETルーチンを行って初めて,リンクが確立するイメージ data wk1; if 0 then set sashelp.class; drop rc dsid; dsid=open("sashelp.class", "i"); call set (dsid); do i=1 to 10; rc=fetchobs(dsid, i); if 13 <= AGE then output; end; stop; run;
【No41】CALL SLEEPルーチン SASの実行を指定時間,停止する デフォルトだと単位がミリ秒のため data _null_; call sleep(1000); run; これで1秒停止になる 第二引数で,単位を設定できて data _null_; call sleep(5,1); run; これだと,第二引数の1秒が基準単位になるので,5秒停止する 小技として,バッチ実行のスケジュール設定すりゃいいだけの話ですが,対面実行で, 夜の○○時まで処理を待機して,〇〇時がきたら動くみたいな処理は data _null_; sleeptime='01Dec2023:03:00'dt-datetime(); call sleep(sleeptime, 1); run;
【No42】CALL SOFTMAXルーチン CALL SOFTMAXルーチンでソフトマックス値の計算をしてくれます.ソフトマックスって言われてもピンとこな い人もいるかもしれないですが,シグモイド関数って聞いたことないですか? 実はソフトマックス関数の2値に 限定したのがシグモイドで,逆に言うと多層化したシグモイドがソフトマックス yを2に固定して,xを-10から10の範囲に動かして,ソフ トマックス値だしてみます data wk1; proc sgplot data=wk1; y=2; series x=i y=x /smoothconnect ; do i=-10 to 10; series x=i y=y /smoothconnect ; x=i; run; call softmax(x,y); data wk1; y=1; output; z=2; end; do i=-10 to run; x=i; 10; call softmax(x,y,z); output; end; run; ソフトマックス変換された値 の合計は必ず1になります proc sgplot data=wk1; series x=i y=x /smoothconnect ; series x=i y=y /smoothconnect ; series x=i y=z /smoothconnect ; run;
【No43】CALL SORTルーチン 数値変数または文字変数を,横方向にソートして値を入れ替える data wk2; set wk1; call sort(of x y z); call sort(of a b c); run;
【No44】CALL SORTCルーチン 文字変数のみを対象としたSORTルーチン data wk2; set wk1; call sortc(of a b c); run;
【No45】CALL SORTNルーチン 数値変数のみを対象としたSORTルーチン data wk2; set wk1; call sortn(of x y z); run;
【No46】CALL STDIZEルーチン proc STDIZEで,行方向に行う標準化を,列方向にたいして行うことができる data wk1; set sashelp.iris; call stdize(of SepalLength SepalWidth PetalLength PetalWidth); mean=mean(of SepalLength SepalWidth PetalLength PetalWidth); std=std(of SepalLength SepalWidth PetalLength PetalWidth); format mean std 8.3; run; 平均0 標準偏差1に標準化
data wk2; set sashelp.iris; call stdize('add=',0,'mult=',100,'range’, of SepalLength SepalWidth PetalLength PetalWidth); run; 最小値を0 最大値を100になるように標準化 data DT1; input A B C; cards; 1 . 2 3 4 . . . 5 run; data DT2; set DT1; call stdize('missing=',0,'none',of _all_); run; 欠損を 定数0で補完
【No47】CALL STREAMルーチン シードから生成される乱数ストリームの系統を切り替えることができる data Sim; call streaminit( 1221 ); do i = 1 to 20; X1 = rand( 'uniform' ); output; end; run; data Sim2; call streaminit( 1221 ); do i = 1 to 10; X1 = rand( 'uniform' ); X2 = rand( 'uniform' ); output; end; run; 変数が 異なっても,呼び出される順番によって,同じ ストリーム(幹てきな)から乱数が取得されているのがわ かる
data Sim3; call streaminit( 1221 ); do i = 1 to 10; call stream(0); X1 = rand( 'uniform' ); call stream(1); X2 = rand( 'uniform' ); output; end; run; X1とX2の前で call streamで ストリームを分離して いるために,X2は sim1のX1とは独立していることがわ かる
【No48】CALL STREAMINITルーチン 乱数の生成にシード値を設定する data a; do i = 1 to 5; X1 = rand( 'uniform' output; end; run; data b; do i = 1 to 5; X1 = rand( 'uniform' output; end; run; data c; call streaminit(123); do i = 1 to 5; X1 = rand( 'uniform' output; end; run; data d; call streaminit(123); do i = 1 to 5; X1 = rand( 'uniform' output; end; ); ); ); );
【No49】CALL STREAMREWIND ルーチン 乱数ストリームを初期化する data a; do i = 1 to 10; X1 = rand( 'uniform' ); if i = 5 then call streamrewind; output; end; run; 5obsでストリームを初期化してるため,6obsから再度 繰り返されている
【No50】CALL SYMPUTルーチン データステップ中から,値をマクロ変数に格納する data _null_; set sashelp.class end=eof; AGE2+AGE; MEAN=AGE2/_N_; if eof then call symput("AGE_MEAN",MEAN); run; %put &=AGE_MEAN;
【No51】CALL SYMPUTXルーチン データステップ中から,値をマクロ変数に格納する. CALL SYMPUTとの違いは ①数値を指定してもログに余計なWARNINGがでない ②オプションで第三引数を指定でき,特に,”G"を指定して強制的にグローバルマクロ変数にできる機能が強力 ③両端の空白を除去 data _null_; data _null_; set sashelp.class end=eof; call symputx("A"," aaaa "); AGE2+AGE; run; MEAN=AGE2/_N_; if eof then call %put &=A; symputx("AGE_MEAN",MEAN,"G"); run; %put &=AGE_MEAN;
【No52】CALL SYSTEMルーチン OSに対して,コマンド実行ができる Xコマンドに似ているが,Xコマンドはデータステップでの条件分岐ができない data _null_; call system('dir /w'); run; options noxwait; data _null_; input flag $ name $8.; if upcase(flag)='Y' then do; command='md c:\'||name; call system(command); end; datalines; Y mydir Y junk2 データステップで,フラグがYの時のみ, N mydir2 コマンドを流すといったことがXステートメントだとできないが call systemだと可能 Y xyz ;
【No53】CALL TANHルーチン 活性化関数のtanh関数(Hyperbolic tangent function: 双曲線正接関数)処理の結果を返す call softmaxルーチンでシグモイド関数の挙動を作って,それと比べると違いがわかりやすい data wk1; y1=2; y2=2; do i=-10 to 10; x1=i; x2=i; call softmax(x1,y1); call tanh (x2,y2); output; end; run; proc sgplot data=wk1; series x=i y=x2 /smoothconnect ; series x=i y=x1 /smoothconnect ; refline 0 0.5; run; オレンジがシグモイド関数で,青の方がtanh関数 値が-1から1をとるため シグモイド関数の微分係数の最大値は0.25と小さいため、勾配が小さくな りがちで学習に時間がかかるという問題があった。そのため学習がより高 速化するように、最大値が1.0となる「tanh関数」がよく採用されるよう になった
【No54】CALL TSOルーチン ★未検証 z/OS環境(いわゆるメインフレーム環境)におけるCALL SYSTEMルーチン 通常のWindows環境やUNIX環境では実行しても 何も起きない
【No55】CALL VNAMEルーチン 【No11】CALL LABELルーチンの変数名バージョン call vname( [こっちに指定した変数の変数名を] ,[こっちの変数に値として戻す]) data wk1; length var $100.; set sashelp.class; array ch _character_; array num _numeric_; do over ch; call vname(ch,var); if ch ne "var" then output; end; do over num; call vname(num,var); output; end; stop; run;
【No56】CALL VNEXTルーチン data wk1; length name type $20.; if 0 then set sashelp.class; do i= 1 to 11; call vnext(name,type,length); output; end; stop; keep name type length; run; 最後に,全変数までいった後に空白が生じる仕様なので, それを利用して doループ+untilの書き方でとることが多い do i= 1 to 1000 until(name=' '); data wk1; length name type $20.; if 0 then set sashelp.class; do i= 1 to 1000 until(name=' '); call vnext(name,type,length); output; end; stop; keep name type length; run;
【No57】CALL TSOルーチン ★未検証 z/OS(メインフレーム環境)専用で,システムコンソールにメッセージをポストするルーチン. Windows環境やUNIX環境では関係なし 通常のWindows環境やUNIX環境では実行しても 何も起きない
過去一,しんどかった. やめておけばよかった ご清聴ありがとうございました