最近ちょっと更新が途絶えてましたが元気です。
さて、昔、人にプログラムをあげた時に
s = sum(of a -numeric- e) ;
みたいな書き方を入れていたんですが、なんですかこれ??って
質問が来たことがあります。
特定の関数で、複数の引数を指定するときの方法として
カンマで区切って列記する方法と、ofで指定する方法があります
(併用もできます)。
が、うっかりしていると慣れた人でもハマりやすい罠があるので
おさらいしてみようと思います。
テストデータ
data Q1;
x1=1;x2=2;x3=3;x4=4;x5=5;
run;
まずは基本。
x1からx5まで全部の合計をだすには例えば以下のように書きます。
data A1;
set Q1;
y1 = sum(x1,x2,x3,x4,x5);
y2 = sum(of x1-x5);
put (y1-y2) (=/);
run;
ログに
y1=15
y2=15
とでます。あってます。
y1は基本で、対象の変数を全部カンマ区切りで指定します。
y2はofを使用しています。
これから詳しく見ていきますが、ofを使うと
①of x1-x10 (変数の末尾の連番指定)
②of id--y (データセットの格納順 idからyまでの間にある変数全部)
③of _all_ や of _numeric_; や of _character_;(全変数や全数値変数や全文字変数)
④of ax{*} (配列を指定)
⑤of x: (コロンモディファイア指定→xから始まる変数名のもの全て)
⑥of x1 x3 x5 (変数列記 変数だけでなく①から⑤までのものを全て空白区切りで列記できる)
といった指定が可能になります(他にもあったら教えてください)。
で、とても便利なのですが、よくやってしまうのが
data A3;
set Q1;
y3 = sum(x1-x5);
put y3=;
run;
結果は
y3=-4
なんで値がマイナスになっているかというと
of をつけないと x1からx5を引いた単一の値がsum関数の対象になってしまってるんですね。
続いて、複数の変数リストを指定する場合ですが
data A4;
set Q1;
y4 = sum(of x1-x2 x4-x5);
y5 = sum(x1-x2 , x4-x5);
y6 = sum(of x1-x2 , of x4-x5);
y7 = sum(of x1-x2 , x4 , x5);
put (y4-y7) (=/);
run;
結果は
y4=12
y5=-2
y6=12
y7=12
y4のようにof の後、空白でリストを区切ればOKです。
先ほどと同様にy5のようにしてしまうと x1引くx2とx4引くx5の値の合計値がでてしまいます。
意外と盲点なのが、y6のようにカンマで区切っても、その中ごとにofをつけてやれば
コードとして正しいということなんですね。
同様にy7のようにof指定とカンマ区切りを併用することもできます。
y4のようにカンマつけなきゃ一つのofで済む話なのに、なんで敢えてこういうことを書くかというと
例えば、プログラム仕様書の条件式や指定変数からコードを自動生成したりする場合、
仕様書の記載法と生成ロジックを考えなきゃいけないわけですが、そういう時に
こういう書き方でも式が正しく成立している(していない)といったケースを多く知ってると意外と役立つと思います。
で、次は、対象の変数に個々にマイナスをかけて合計したい場合です。
質問方向が反転の項目とかでそういうことありますよね。
以下を実行すると
data A5;
set Q1;
y8 = sum(-x1,-x2,-x3);
y9 = sum(of -x1 -x2 -x3);
put (y8-y9) (=/);
run;
結果は
y8=-6
y9=.
となってy8は正しいですがy9は正しく計算されません。
ofの場合、カンマ区切りと違ってマイナスつけはできないのです。
マイナスつけができないというより、もっと広く言えば
以下のように
data A6;
set Q1;
y10 = sum(x1+x2,x1*x2);
y11 = sum(of x1+x2 x1*x2);
put (y10-y11) (=/);
run;
結果は(y11のせいでエラーになりますが個別にだすと)
y10=5
y11=.
つまり、ofは変数の一括指定のためのキーワードで計算式を引数には
とれないうことです
さて次は、of使うといろいろできるよという例ですね
data A7;
set Q1;
array x{*} x: ;
y11 = sum(of x{*});
y12 = sum(of x{*} , x2 , of x3-x5 , of x:);
put (y11-y12) (=/);
run;
結果
y11=15
y12=44
y11についてはカンマで区切らなければofは一個で、後は空白区切りでOKですからね。
最後は冒頭で述べた例に戻ります。
以下のテストデータがあり
data Q2;
a=1;b=2;c=3;d='AAA';e=4;
run;
--を使うことによって変数の格納順を利用できます。
data A8;
set Q2;
y13= sum(of a--c);
put y13 = ;
run;
結果
y13=6
で、以下の例のy13のように_numeric_としてデータセット内の
全数値型変数を対象にできるのですが、
さらにそれを--と組み合わせてy14のようにかくと
data A9;
set Q2;
y14 = sum(of _numeric_);
y15 = sum(of a -numeric- e);
put (y14-y15) (=/);
run;
y14=10
y15=10
aからeの間に格納されている変数のうち、数値型のものに
限るという指定ができます。
ながながと細かい話でした
0 件のコメント:
コメントを投稿