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

【疑問】IF THEN 直後のサブセット化IFの挙動 どなたかお知恵を

最近あった、僕がうまく解釈できなかった事象について書きます。
どなたか、わかる方がいらっしゃればお力を貸してください。

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

data Q1;
X=1;Y=2;Z=3;output;
X=2;Y=3;Z=4;output;
X=1;Y=1;Z=3;output;
run;








それに対してSASを勉強中のYさんが
「X=1であるデータのうち、Y=2のデータのみを抽出したくて、こう書いたのですが
うまくいきませんでした。何が間違ってますか?」
と言ってきて、コードを見てみると

data E1;
 set Q1;
 if X=1 then if Y=2;
run;

でした。

僕はいいました
「なんだこの変な書き方。その条件なら、日本語の文章に惑わされず
 andで結ぶだけじゃない?」

data A1;
 set Q1;
 if X=1 and Y=2;
run;






まあ、Yさん的には目的の処理が書けてこれでOKなのですが、
問題は

data E1;
 set Q1;
 if X=1 then if Y=2;
run;

がエラーもワーニングなく実行できるということです。
僕はてっきりエラーになると思っていました。
エラーにならないのなら、andで結んだのとおんなじ結果かな?と思いました。
if X=1 の場合にサブセット化IFでY=2がかかるのかと、、。
ところが結果は以下のようになりました。






なにこれ?どういう処理がされたらこんな結果になんの??
X=1で絞れているわけではないし、Y=2でも絞れてないし、なんで2obs?
しかも2レコード目はなんで出てきた??

しばらく考えたのですがわかりませんでした。

ちなみにどうしてもandを使わず、if 今回の処理をするならどう書くかを考えると

data A2;
 set Q1;
 if X=1 then if Y=2 then output;
run;

が思い浮かんだので実行すると、これは正しい結果を導きました。





じゃあ、以下のコードも通るよねと考えました

data E2;
 set Q1;
 if X=1 then if Y^=2 then delete;
run;

しかし、また変な結果です。






なんで??
絶対、if X=1 then if Y=2;なんて第一感悪手で実戦では本能的に書かないからいいんですけど
、どうしてもひっかかる、気になります!気になるんです

if then ステートメントの後に、if 条件式だけを書いたり、
if then deleteを書くと、変な結果になるのはなぜなんでしょうか??

どなたか、推論でもいいので教えてください。

=======================
追記
=======================
解決しました!的確で素晴らしいコメントをいただきました!
詳細はコメント欄をみてください。
また一つ賢くなれた気がします。

ちなみにコメントくださったのはブログ「SAS忘備録(URL http://sas-boubi.blogspot.jp/)」
の作者様です。
SAS忘備録は、本当に素晴らしくて、僕のと違って文章が読みやすいし押しつけがましくないし
丁寧ですし、書かれていることも洗練された役にたつ知識ばかりで、見習いたいです。



推理詰め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に落とし込んでくる以前に判定がかかるので、型変換が発生せず、式の演算子にたいする互換性エラーになります。