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

データセットオプションの適応順の推測

自分がしょっちゅう間違えるので、自分のために整理します。

さて

data Q1;
 do X=1 to 10;
  output;
 end;
run;

のデータセットがあります。


以下の①から④までのプログラムを実行したとき
エラー・ワーニングがでずに、きちんとYにリネームされた
データセットが作成されるのはどれでしょうか??

/*①*/
proc sort data=Q1 out=A1(rename=(X=Y) where=(X>5));
 by X;
run;

/*②*/
proc sort data=Q1 out=A2(rename=(X=Y) where=(Y>5));
 by X;
run;

/*③*/
proc sort data=Q1 out=A3(rename=(X=Y) keep=X);
 by X;
run;

/*④*/
proc sort data=Q1 out=A4(rename=(X=Y) keep=Y);
 by X;
run;


なんか、SAS BASEの資格試験にでてきそうな、いやらしい問題ですね



まず
【①の結果】








データセットは作成されません


【②の結果】








【③の結果】









【④の結果】









WARNINGだけですが、データセットは作成されてません


というわけで

×


×

でした。


推理するに、データセットオプション内でのステートメントについて
keep → rename → where
の順で適応されているということでしょうかね。

たぶん、きちんと資料読めば、どっかに書いてあるんでしょうか、とりあえずここまで






same演算子でwhere式の置き換えではなくwhereの追加を行う

前の投稿でwhere特有のcontainsやbetween等を紹介しましたが、今回はsameです。
一緒にするには少し毛色が違ったのでわけました。

さて今、以下のようなデータセットがあったとします。

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









そこに

data A1;
 set Q1;
 where X>2;
 where X<4;
run;

を実行すると、何がおきると思いますか?
whereステートメントが連続で、でてきます。

え、エラーじゃないの?と思われた方は不正解で、正しく実行されます。

結果は







となり、ログをみると













WHERE式を置き換えました」というNOTEがでています。
つまり、一つ目のWHEREは二つ目に上書きされて、無効化されてしまったのです。
最後にくるWHEREだけが効きます。

もし、今やりたいことが「X>2」「 X<4」の2条件で抽出をかけることであれば

当然

data A1;
 set Q1;
 where X>2 and X<4;
run;

でいいわけです。

が、しかし、次のようにも書くことができます。
それが

data A2;
 set Q1;
 where X>2;
 where same X<4;
run;


















ですsameをつなぐことによって
whereステートメント同士をandでつなぐのと同じ効果があります。
WHERE式を追加しました」というNOTEがでます。

で、どういう時に使うかというと

抽出式があまりに長くなって見通しが悪い時や、
元コードをできるだけ修正せずに、新しい条件を追加したい場合、
マクロ化して、抽出条件をオプションで追加できるように組む場合等でしょうか?

条件を色々追加しながら対話的に、データを段階的に絞りこんで探索する場合なんかも
いちいち and ○○とかいていくより、区切りがつくのでお勧めです。
















推理詰めSAS①似て非なるもの

推理将棋というのをご存知でしょうか?
ある将棋について、その将棋の局面にたいする会話文が提示され、その会話の内容から
どんな将棋であったか、例えばどういう手順で詰んだのかを推理するゲームです。

最近、新たにSASを覚えようとしているYさんにSASを教えていて、よく質問に来てくれるのですが
その時の私とYさんの会話の内容から、いったいYさんがどんな間違いをしたのかを推理してください。

Yさん
「すみません、IFで書くと通るんですけど、WHEREで書くとエラーになるんです。この間、その2つは同じように使うことができるって教えてくれましたよね?」


「確かにWHEREステートメントとサブセット化IFステートメントで、同じ結果を得ることはできるけど、少し機能が違うからね。もしかして、抽出元のデータセットにない変数に対して抽出をかけようとしてるんじゃない?それなら、IFは通っても、WHEREは通らないね」

Yさん
「違います。確かに抽出条件にしている変数は元のデータセットにあります。変数名も、使用する不等号も間違っていないのに、WHEREのときだけ、なんか演算子がどうとかってエラーになるんです」


さて、ほぼ実話ですが、この情報だけで、Yさんがどういった間違いを犯しているのか特定できますでしょうかというのが問題です。
答えが一つかどうか、ちょっと微妙ですが、まあYさんはそんなに複雑なことはそもそもできないので、単純なミスだと考えてください。



【解答】
Yさんは

data A;
X=1;
run;

のようなデータセットに対して

data A1;
set A;
if X='';
run;

というプログラムを書いていました。
変数の型を間違えて抽出式を書いています。
この場合、確かにIFなら一応通ります。

data A1;
set A;
where X='';
run;

しかしWHEREならエラーになります。





これはつまり、サブセット化IFはいったん全オブザベーションに対しての処理が行われるからですね、PDVにひっぱりこんで、不等式にかける際に、暗黙の型変換が適用され、文字型として抽出式にかけられます。

しかしWHEREはその前段階、PDVに落とし込んでくる以前に判定がかかるので、型変換が発生せず、式の演算子にたいする互換性エラーになります。