retainステートメントに配列指定できる話

もしかしたら、初等技術なのかもですが、最近初めて知った話です。

例えば












があって、
Xで重複を消して、Yを使って、Zを横展開しろと言われたら
迷うことなく

proc transpose data=Q1 out=A1(drop=_NAME_) prefix=Z_;
 var Z;
 by X;
 id Y;
run;









ですね。

一番好きなプロシージャはと訊かれたらtransposeと答える僕なので
(訊かれたこと一度もありませんが)、これ以外のやり方がぱっと思いつかないんですよね。

ただ、最近知ったのが

proc sql noprint;
 select max(Y) into:MY
 from Q1;
quit;

data A2;
 set Q1;
 by X;
 array Z_{&MY};
 retain Z_;
 if first.X then call missing(of Z_{*});
  Z_{Y}=Z;
  if last.X then output;
 drop Y Z;
run;

で、この場合結果は同じです。
Yの値が例えば1と4だけなどで飛び値になっている場合、transposeだとZ_1とZ_4だだけが作られますが、こちらの方法だとZ_2とZ_3もnullで作成されるので、ケースによって使い分けれそうです。

何が面白いって、retain 配列名が通るんですね!確かに、通りそうですけど、意外と
その発想がなかったです。


あとついでに関係ないけど、これまた最近知った

data A3;
array AX{2,3,4}(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
 D1=dim(AX);
 D2=dim2(AX);
 D3=dim3(AX);
keep D1 D2 D3;
run;





へ~dim関数って dim2 dim3とかにして、次元ごとの数とれるんですね!
いつも1次元でdim使ってたけど、dim1ってことだったのか~

2 件のコメント:

  1. AX全体の要素数は、次のようにすれば一応できましたが、問題点も。
    もっと簡単にできるのでしょうか?
    簡単にできるからと言って用途はあまりありませんが。

    array AX{2,3,4};
    array AA{*} AX:;
    D=dim(AA);
    put D=;

    返信削除
  2. 有難うございます!う~ん、多分なさげですよね~。いただいたように1次元配列で再定義するかD=dim(AX)+dim2(AX)+dim3(AX);みたいな単純な方法しか浮かばないですで。array周りの機能がもう少し拡張されてもよさそうなものですが、、。

    返信削除