例えば
data Q1;
do X=1 to 10;
output;
end;
run;
のようなデータセットがあったとして、そこから、
ひとつ前のオブザベーションの値を変数「LX」にいれる、ただし先頭については
ひとつ前のオブザベーションが存在しないので、循環して最後の値をとってくるという
問題があったとします。
目的とするデータセットは以下の形です。
↓【目的局面図】
さて、どう解くのが最短でしょうか?
ちなみに1手詰めです(1ステップで処理できる)
まず、LAG関数が第一感で思い浮かぶ方が多いかと思います。
data A;
set Q1;
LX=lag(x);
run;
しかし、これだと循環が表現できません。
当然こうなります。
LAG関数の使用は、今回はドツボ行きです
【解法】
data A1;
set Q1 Q1 nobs=tobs;
LX=X;
if _N_<tobs/2 then delete;
set Q1;
run;
nobs=やend=はsetで複数のデータセットを指定した際にまとめての値しかだせません。
なので上記でのnobsの中身は20です。
そこでサブセット化IFで1-9番目のオブザベーションをdeleteしているので
この時点で残っているのは10,11,12,13,14,15,16,17,18,19,20の11オブザベーション
つまり、ケツの1オブザベーションを頭に乗っけた形で11obsのデータセットが一時的に
できているわけです。
そこで、さらにSetを打つわけです。
おさらいですが、Set;Set;は一度でもファイル終端をどこかのデータセットで見つけたら
処理が打ち切られるので、結果として指定されたデータセット中、最小のオブザベーション数で
まとめられるという性質を持っています。
11obsと10obsをSet Setしているわけなので、作成されるデータセットは10obsです。
説明が下手なので、もしピンと来なければ実際に動かしてみてください。
こんにちは。
返信削除いつも参考にさせて頂いてます。
説明されてる方法はパズル的な解き方で面白いですね!
おもわず「あ~なるほど~」と言ってしまいました笑
わたしはなんの捻りもないSETステートメントのPOINTを使ったやり方を思いつきましたが、色々な解き方を考えるのも結構楽しいですね!
↓ちなみにわたしが考えた方法です。
data A1;
set Q1 NOBS=TOBS;
PNT=_N_-1;
if PNT<1 then PNT=TOBS+PNT;
set Q1(rename=(X=LX)) point=PNT;
run;
ありがとうございます!!
削除見てくれて本当にありがとうございます。
いっつも、間違ったコードを垂れ流していてすみません。
あ~、やられました。
ご指摘いただいたコードの方が無駄がない。スマートですね。
こっちを最適解にしましょう。
でも、
PNT=TOBS+PNTの部分の+PNTは要らないんじゃないですかね??
_N_=1の時だけケツ(point=TOBS)からとるようにしているんで、+PNTのところは条件式を通る時は必ず0じゃないです??
意図を読み切れていなかったら赤っ恥ですが、、、
たしかに今回の目的局面だと「+PNT」は要らないです。
返信削除入れている理由として
たとえば目的局面が「3個とか4個とかずらしたい」っていう場合に、
「PNT=_N_-1;」の部分を
「PNT=_N_-3;」とか変えれば3個ずれてくれるので、応用が利くかなぁと思って「+PNT」を入れてみました。
あぁ、そうか!そうですよね!しまった!
削除重ね重ね有難うございます!!
今後もぜひ、よろしくお願いします