ラベル indsname= の投稿を表示しています。 すべての投稿を表示
ラベル indsname= の投稿を表示しています。 すべての投稿を表示

inオプションは1データセット1回しか使えないっぽい話

今、以下の二つのデータセットがあって

data Q1;
X=1;
run;





data Q2;
X=2;
run;






上の2つから下のデータセットを作る必要がありました








これはまず、Q1のオブザベーションを2倍にコピーして、
最初の値にだけ5を加える。
それをQ2に対しても行う。
両方を縦に結合して、Q1由来の場合はYの値を1、Q2由来の場合はYを2としたことで
作成できます。

僕はまず、ぱっと
data A0;
 set Q1(in=in1 in=ina)
     Q1(in=ina)
     Q2(in=in1 in=inb)
     Q2(in=inb)
;

if in1 then X=X+5;
if ina then Y=1;
if inb then Y=2;

run;

というコードが浮かびました。ただ、書いた瞬間に、あ~これは通らなさそうだなぁという感触が
ありました。

案の定、結果は









となりました。つまりin=in1が効いてないわけです。
ということはすなわち、in=は複数指定できないというわけです。

一応(in=in1 ina) とか(in=in1,ina)とか、記述法を思いつく限り試してみましたが、やっぱり無理でした。
in=が複数指定できるとコードの自由度爆発だから、いつかできるようにならないかな、、、。


まあ、結局、このケースの場合はinで複数指定できない分
indsname=オプションで代用することで実現できましたが、データセット名がカギになる
ケースしか使えんし、イマイチです。

data A1;
 set Q1(in=in1)
     Q1
     Q2(in=in1)
     Q2
indsname=NAME;
;

if in1 then X=X+5;
if NAME='WORK.Q1' then Y=1;
if NAME='WORK.Q2' then Y=2;

run;





indsname定跡

indsname=オプションが気になっていて、面白そうだから、何かの処理に活用したいんだけど、いい使い道がわからないので教えてくださいというご連絡を匿名で直接いただきました。

手段のために目的を探すその姿勢、僕は大好きです、とても共感します。

というわけで、僕の中で定跡となっているindsnameを使った手順を紹介します

あ、ちなみに以前のindsname=の記事は
http://sas-tumesas.blogspot.jp/2013/10/indsname.html
です。



さて、今、WORKの中にたくさんのデータセットがあったとします。

data Q1;
ID='0001';output;
ID='0002';output;
ID='0003';output;
ID='0001';output;
run;

data Q2;
ID='0006';output;
ID='0002';output;
ID='0004';output;
ID='0003';output;
run;

data Q3;
ID='0005';output;
ID='0002';output;
ID='0004';output;
ID='0003';output;
run;

data Q4;
ID='0005';output;
ID='0001';output;
ID='0004';output;
ID='0003';output;
run;

data Q5;
ID='0001';output;
ID='0001';output;
ID='0001';output;
ID='0003';output;
run;


















さて、これらのデータセットの中で変数「ID」の値が0001のデータを含むデータセットの名前と
0001のデータのオブザベーション数を抽出したデータセットを作成しなさいと言われたら、
どういった処理を書くでしょうか?

要するに求めたい結果は


こんな感じです。

やり方はたくさんあると思いますが、僕はこういったケースの場合

data ALLDS;
 set Q: indsname=NAME;
  DSNAME=scan(NAME,2,'.');
run;

proc freq data=ALLDS noprint;
 tables DSNAME*ID/out=A(drop=percent ID);
 where ID='0001';
run;

こう書きます。

2ステップですが、わかりやすいです。

freqに書ける前のALLDSの中身は






















こんな感じです。


これって結構応用が利いて、
複数のデータセットを対象として、何か条件をかけて
その結果とデータセットの名前を、結果としたデータセットを作りたい時にわかりやすいです。

GLOBALのユーザー会でも、まだほとんど見かけないので、開拓の余地があるオプション
だと思います。テーマにするなら狙い目じゃないでしょうか。










indsname オプションで、由来元のデータセット名を取得する

9.2になって追加された機能で、これが一番凄い!と何回も言っていて狼少年状態です
例えば

・proc transposeのidステートメントに複数変数を指定可になったのが最高!!
・データセット名にコロンモディファイアで前方一致をかけれるようになったのが最高!!

多分、他にも言っていた気がします。

でも、今回紹介するindsnameも負けず劣らず使える機能です。
例えば以下のような2つのデータセットA Bがあったとします。

data A;
 do X=1 to 5;
  output;
 end;
run;

data B;
 do X=1 to 5;
  output;
 end;
run;

そこから、データを縦結合して
各オブザベーションの由来元がわかるようにする場合

data C;
 set A(in=ina)
     B(in=inb);
 if ina=1 then DS='A';
 if inb=1 then DS='B';
run;


みたいなコード書いていたと思います。 多分。

それがINDSNAMEオプションを使えば

data D;
 set A B indsname=inds;
  DS=inds;
run;
 


となります。

これは結構凄くないですか?ライブラリ名までとれます。
デバックする時やコードレビュー等で、
一体このオブザベーションはどっから来てんだ?みたいなのを手繰っていきたい時ってあると思います。
もしかしたら、長い人生のうち
導出されたデータセットと導出プログラムはあるが、導出仕様書がないといった
悲惨な現場に遭遇することもあるかもしれません。

そんな時に凄い良いです。

これもっとテクニカルニュースとかで取り上げていいんじゃないでしょうか?
僕は海外のコードを見ていて初めて知りました。
日本のSASの情報環境、ちょっとやばいですよね、なんとかしないと