Nオブザベーション先の値を取得する話①

Nオブザベーション前の値を保持して取得する場合,retain使ったり,lag関数使えばよいのですが(lag関数の注意点参照 https://sas-boubi.blogspot.com/2021/05/lag.html)
data A;
set sashelp.class;
pre1_age=lag(age);
pre2_age=lag2(age);
keep name age pre:;
run;




これを逆にしようと思うと,1obs読んで1obs出力するSASの仕組み的にはつらいものがあります.
もう一回sort順逆にして前のobsをとれば一応は先をとったのと同じことにはなりますが
データが巨大だったりすると,みだりにソートやステップを重ねることが難しかったりします

data B ;
set sashelp.class(drop=height weight);
_DSID = open("sashelp.class(keep=age rename=(age=_age))") ;
call missing(_age);
call set(_DSID) ;
rc = fetchobs(_DSID, _N_+1) ;
if rc ne 0 then call missing(_age);
run;

open関数でsetと同じデータセットを指定して,IDづけして
setしてる親元の_N_に+1した数で,任意のobsをブッコ抜くfetchobsでもってくる.
欲しい変数のみ残していて,リネームしているので結果的にリネーム結合と同義になる
ハッシュオブジェクトと同じくPDV外からきた変数は,PDVでの値のクリーンアップがかからないので,retainされてしまう.そこでリターンコードrcを処理にからめる
rcはfetchobsが成功,つまり1obs先がある場合のみ0なので,0以外の場合は初期化
SCL関数をデータステップ内で使った場合,終了時に自動でcloseがかかるのでclose関数は省略

これをマクロで汎用化するなら
%macro next_look(master=,var=,postn= );
if 0 then set &master(keep=&var rename=(&var=next&postn._&var));
length &master.&var.&postn. 8.;
retain &master.&var.&postn.;
if missing(&master.&var.&postn.) then do;
&master.&var.&postn. = open("&master(keep=&var rename=(&var=next&postn._&var))") ; 
call set(&master.&var.&postn.) ;
end;
rc = fetchobs(&master.&var.&postn., _N_+&postn) ;
if rc ne 0 then call missing(next&postn._&var);
drop &master.&var.&postn. rc ;
%mend;

こんなの
data C ;
set sashelp.class;
%next_look(master=sashelp.class,var=name,postn=1);
%next_look(master=sashelp.class,var=age,postn= 1);
%next_look(master=sashelp.class,var=age,postn= 2);
keep name age next:;
run;


でも,優秀な後輩からの指摘で,それなら単純にpoint setの方が速度でるんじゃねえっすか?
ってことで

data z;
set sashelp.class;
__n = _n_ + 1;
if 1 <= __n <= nof then set sashelp.class(keep = age rename = (age = next_age)) point = __n nobs = nof;
else call missing(next_age);
keep name age next_age;
run;


確かにねー.

で,巨大なデータにしてみたり,色んなシチュエーションで実験してみたけど
fetchobsもパフォーマンス悪くはないけど,常にpoint setの方がややいい感じ.

簡素性や,SCL関数とか下手に使ってない観点からしてもset pointの方がいいですね

いやー,できる後輩がいると辛いですね(笑)

次回は,いつになるかわからないですが,条件付きで先を見る話です
(○○時間経過以内の特定の値をとるとか,そのobsの先に特定条件を満たすものがあった場合のみ取得する みたいなものには単純な割り当て法だとつらい)


0 件のコメント:

コメントを投稿