SAS忘備録
・本人の備忘録として。
・日本でもSASを活発化させたい。
2024年6月2日日曜日
【PROC FORMAT】数値フォーマットの落とし穴
2023年5月7日日曜日
「PROC REPORT」の「COMPUTE」がうまく動かないんだけど②
- まず、XをORDER変数にしています。またORDER変数が欠損値のオブザベーションも出力対象とするため、MISSINGオプションを指定。
- 次にCOMPUTEで「if x=. then z="Y"」として、Xが欠損値のオブザベーションに"Y"のフラグを立てたんですが、、想定では1、2オブザベーション目だけに"Y"が入るはずなのに、4、6オブザベーション目にも"Y"が入っている?!
あと、失敗例①を知っちゃうと、なんとなく以下のようになるのでは?と思っちゃいません?(失敗例①で「X=.」と判定されたオブザベーションが、今回「X=2」になると思ってしまった)
ORDER変数(GROUP、ANALYSIS、ACROSS変数とかも?)に対して、COMPUTEで値をいじると、うまく絡み合ってくれなくて、想定外の結果になる場合があるのでご注意ください。
そもそも元の変数値をPROC REPORT上でいじるのって、あまりやらない、というか良くないのかも?
2023年5月4日木曜日
2023年4月22日土曜日
サブセット化IFでありがちな落とし穴
SASプログラマ歴が長いと、みんなこれ経験してるんじゃなかろうか。
😕失敗例1: 「_N_」と組み合わせて失敗しがち
変数Xに1~連番を入れたいのに、なんかおかしい。
解説
- まずデータステップは内部の動きとして、
- 次に「_N_」は内部の動きとして、
_N_=1 のオブザベーションがたまたまサブセット化IFによって「処理継続・出力」の対象外になっているので、「IF _N_=1 THEN DO; ~END;」の中の処理も動いていません。
上の例ではエラーが出て分かりやすいですが、書き方によってはエラーが出ない場合もあって失敗に気づかない可能性もあるので要注意です。
😕失敗例2: 「END=オプション」と組み合わせて失敗しがち
data dt3; set sashelp.class end=_eof; if age=12; if _eof then y=1; keep age y; run; |
フラグ立ってないじゃないか!
これは「END=オプション」の挙動を勘違いしていると起こりやすいです。
「END=オプション」はSET文・WHERE文で読み込まれる最後のオブザベーションに作用しますが、その最後のオブザベーションがサブセット化IFによって「処理継続・出力」の対象外になっているためです。
あと思いつくのが、以下で紹介している「FIRST.BY変数」「LAST.BY変数」も、サブセット化IFと組み合わせると、同様の原理で意図しない結果になりやすいですね。
「FIRST.BY変数」と「LAST.BY変数」で、グループ毎の最初と最後のオブザベーションを特定する。
2023年1月1日日曜日
SASで年賀状2023
SASで年賀状をつくりました(ほぼ「SASで年賀状」の焼き直し)
2023年もどうぞよろしくお願いいたします!
年賀状をつくるプログラム (SAS9.4M7で動作確認)
*** 描画用のパーツ ; data rabbit; x1= 0; y1= 0; x2= 0; y2=-6.5; x3=-0.31; y3= 1.2; x4= 0.31; y4= 1.2; x5= 0; y5= 0.15; x6= 0; y6= 0.7; x7=-0.5; y7= 5; x8= 0.5; y8= 5; x9=-0.5; y9= 5.5; x10=0.5; y10=5.5; x11=-0.8; y11=0.1; x12=0.8; y12=0.1; run; *** 描画 ; title ; ods graphics on / height=10cm width=14.8cm; proc sgplot data=rabbit noautolegend; styleattrs wallcolor=khaki; /* Text */ inset "HAPPY NEW YEAR" / position=top textattrs=(color=brown size=31cm); inset "20" / position=bottomleft textattrs=(color=brown size=140cm ); inset "23" / position=bottomright textattrs=(color=brown size=140cm ); /* rabbit */ scatter x=x1 y=y1 / markerattrs=(symbol=circlefilled size=3cm color=white); scatter x=x2 y=y2 / markerattrs=(symbol=circlefilled size=4cm color=white); scatter x=x3 y=Y3 / markerattrs=(symbol=circlefilled size=0.2cm color=black); scatter x=x4 y=Y4 / markerattrs=(symbol=circlefilled size=0.2cm color=black); scatter x=x5 y=y5 / markerattrs=(symbol=ArrowDown size=0.5cm color=black); scatter x=x6 y=y6 / markerattrs=(symbol=TriangleDownFilled size=0.2cm color=black); scatter x=x7 y=y7 / markerattrs=(symbol=CircleFilled size=1cm color=white); scatter x=x8 y=y8 / markerattrs=(symbol=CircleFilled size=1cm color=white); scatter x=x9 y=y9 / markerattrs=(symbol=CircleFilled size=1cm color=white); scatter x=x10 y=y10 / markerattrs=(symbol=CircleFilled size=1cm color=white); scatter x=x7 y=y7 / markerattrs=(symbol=CircleFilled size=0.7cm color=mistyrose); scatter x=x8 y=y8 / markerattrs=(symbol=CircleFilled size=0.7cm color=mistyrose); scatter x=x9 y=y9 / markerattrs=(symbol=CircleFilled size=0.7cm color=mistyrose); scatter x=x10 y=y10 / markerattrs=(symbol=CircleFilled size=0.7cm color=mistyrose); scatter x=x11 y=y11 / markerattrs=(symbol=CircleFilled size=0.4cm color=pink); scatter x=x12 y=y12 / markerattrs=(symbol=CircleFilled size=0.4cm color=pink); xaxis min=-3 max=3 display=none; yaxis min=-5 max=1 display=none; run; |
2022年11月29日火曜日
SQLプロシジャのINTO句の注意点
SQLのINTO句を使用する際の注意点を2つ紹介したいと思います。
1. 変数にフォーマットが割り当てられている場合
data DT1; format X yymmdd10.; X=1; run; proc sql noprint; select X into :X trimmed from DT1; quit; %put &X; ログ 1960-01-02 |
マクロ変数にはフォーマットをあてた値が格納されるようです。この挙動、SASのリファレンスに書いてない気がする。。
proc sql noprint; select X format=best16. into :X trimmed from DT1; quit; %put &X; ログ 1 |
2. 数値変数かつフォーマットが割り当てられていない場合
data DT2; X=123.456789; run; proc sql noprint; select X into :X trimmed from DT2; quit; %put &X; ログ 123.4568 |
デフォルトの挙動として「BEST8.」の出力形式で格納されるようです。
状況によっては、もとの数値がだいぶ削られちゃいますね(これはINTO句に限ったことではないですが。。)
2022年7月9日土曜日
【PROC FORMAT】CNTLIN=オプションの落とし穴
まず、前提知識として「PROC FORMAT入門9 : CNTLIN=オプション 」をご参照下さい。
そして、ここから本題。以下の例をご覧ください。
失敗例
①まず「データセット」から「フォーマット」を生成
②実データに先ほどのフォーマットを当ててみる。
あれ?!
フォーマット当てた結果、2行目の欠損値に「その他」が当てられてしまってる?!
解説
「CNTLIN=」に使用するフォーマット生成用のデータセットに注目
実は上の "OTHER" が、範囲指定としての「OTHER」として解釈されてしまってます(範囲指定?という方は「PROC FORMAT入門3 : 範囲の指定」を参照)
要は、以下のようにFORMATプロシジャで①みたいな定義をしたつもりが、②の定義をしてしまった、ということ。
proc format; /* ① */ value $TEST_ "OTHER" = "その他" ; run; proc format; /* ② */ value $TEST_ OTHER = "その他" ; run; |
余計なことをしてますね。。
ちなみに、"OTHER" 以外にも、FORMATプロシジャの予約語的なキーワードは気を付けた方が良いです(色々実験してみたところ、"LOW", "HIGH" なども同様に範囲指定の意味として解釈されてしまいました。たぶん他にもあると思います)
解決策
今回の例では "OTHER" を範囲指定の意味ではないと明示してあげる必要があります。上でフォーマットを作り直したので、再度このフォーマットをあてたデータセットを見てみましょう。
はい!さっきまで2行目の欠損値が「その他」になっちゃってましたが、今度は問題なさそうです。
最後に
私が把握しているのは "OTHER", "LOW", "HIGH" のみで、その他にFORMATプロシジャの予約語的なキーワードに引っかかるものがあるかもしれません。
今回の場合だと"OTHER"に対してHLOという変数を作ってNullに設定することで解決しましたが、その他の私が把握していないキーワードに対して、各自SASのリファレンスや「PROC FORMAT入門9 : CNTLIN=オプション」などを参考にして、他の必要な変数を設定してあげる必要があります。