2018年9月26日水曜日

2つの文字を大文字・小文字区別せずに比較する





クマのプーさんの実写映画のやつ観に行ってきました。
プーさんが異常に可愛かったです。あとプーさんってぬいぐるみ設定だったんですね、知らなかった。。




プーさんの話は置いといて、
タイトルの通り、2つの文字を大文字・小文字区別せずに比較する方法を紹介したいと思います。


サンプルデータ
data test;
input a:$10. b:$10.;
cards;
pooh POOH
honey hunny
;



方法①
data out1;
  set test;
  if upcase(a) = upcase(b) then same_flg=1;
run;



半角のアルファベットを大文字にするupcase関数を使っています。
両変数を大文字にして比較しています。



方法②
data out2;
  set test;
  if compare(a,b,'i') = 0 then same_flg=1;
run;



compare( 対象変数1, 対象変数2, 'i' )」というように、3つめの引数に「'i'」と指定することで大文字・小文字区別せずに比較することができます。
戻り値が「0」なら一致してるということです。

(ただし、compare関数は日本語などのマルチバイトの文字には対応していないので、マルチバイトを含む場合は使用できません!ご注意ください!!)



どっち使うかは好みの問題ですね。
例えるなら、upcaseを使う方法はプーさんで、compare関数を使う方法はピグレットみたいな。





2018年9月18日火曜日

【OPTIONS APPEND / INSERT】システムオプションに設定値を追加する。




「APPENDシステムオプション」または「INSERTシステムオプション」を使うと、特定のシステムオプションの既存の設定値に、更に設定値を追加することが出来ます。

何言ってるの?って感じだと思うので、例をご覧ください。



以下、FMTSEARCHシステムオプションの設定値をログに出力しています。

%put %sysfunc(getoption(fmtsearch));

ログ
(WORK LIBRARY)


WORK、LIBRARYの順に設定されていますね。




「APPENDシステムオプション」を使う

options append=(fmtsearch=myfmt);
%put %sysfunc(getoption(fmtsearch));

ログ
(WORK LIBRARY MYFMT)



MYFMTというライブラリが末尾に追加されました。
APPENDシステムオプションは、システムオプションの末尾に設定値を追加することが出来ます。


構文

 OPTIONS APPEND=( システムオプション名 = 末尾に追加する設定値 );





「INSERTシステムオプション」を使う

options insert=(fmtsearch=myfmt2);
%put %sysfunc(getoption(fmtsearch));

ログ
(MYFMT2 WORK LIBRARY MYFMT)



MYFMT2というライブラリが先頭に追加されました。
INSERTシステムオプションは、システムオプションの先頭に設定値を追加することが出来ます。


構文

 OPTIONS INSERT=( システムオプション名 = 先頭に追加する設定値 );






その他メモ


FMTSEARCH、SASAUTOSなどで設定値の追加をすることができます。
ただし、以下のように何回も実行すると、同じ設定値が追加され続けちゃうんで、気を付けてくださいね。

options append=(fmtsearch=abc);
options append=(fmtsearch=abc);
%put %sysfunc(getoption(fmtsearch));

ログ
(WORK LIBRARY ABC ABC)





2018年9月10日月曜日

PROC SQL / FedSQL / DS2 の「STIMERオプション」でログに各ステップ毎のパフォーマンスを表示する





以下はPROC SQLで何個かステートメントを書いて実行した結果

proc sql;
  create table dt1 as select * from sashelp.class;
  create table dt2 as select * from sashelp.cars;
quit;



ログ
 72         proc sql ;
 73           create table dt1 as select * from sashelp.class;
 NOTE: テーブルWORK.DT1(行数19、列数5)が作成されました。

 74           create table dt2 as select * from sashelp.cars;
 NOTE: テーブルWORK.DT2(行数428、列数15)が作成されました。

 75         quit;
 NOTE: PROCEDURE SQL処理(合計処理時間):
       処理時間           0.00 秒
       CPU時間            0.01 秒



続いてSTIMERオプションをつけた場合

proc sql stimer;
  create table dt1 as select * from sashelp.class;
  create table dt2 as select * from sashelp.cars;
quit;


ログ
 74         proc sql stimer;
 NOTE: SQL Statement処理(合計処理時間):
       処理時間           0.00 秒
       CPU時間            0.00 秒
     
 75           create table dt1 as select * from sashelp.class;
 NOTE: テーブルWORK.DT1(行数19、列数5)が作成されました。

 NOTE: SQL Statement処理(合計処理時間):
       処理時間           0.00 秒
       CPU時間            0.00 秒
     
 76           create table dt2 as select * from sashelp.cars;
 NOTE: テーブルWORK.DT2(行数428、列数15)が作成されました。

 NOTE: SQL Statement処理(合計処理時間):
       処理時間           0.00 秒
       CPU時間            0.00 秒
     
 77         quit;
 NOTE: PROCEDURE SQL処理(合計処理時間):
       処理時間           0.00 秒
       CPU時間            0.00 秒


ログにステートメント毎のパフォーマンスが表示されるようになります。
「PROC DS2」や「PROC FedSQL」でも同様にSTIMERオプションを設定できます。
私自身はDS2使う時によくこのオプション指定することはあります。


※「STIMERオプション」を利用するには、システムオプションで「OPTIONS STIMER」か「OPTIONS FULLSTIMER」も設定されている必要があります。


2018年9月4日火曜日

PROC DS2でタイムゾーン関係の処理をする「TZパッケージ」



DS2プロシジャの「TZパッケージ」でタイムゾーン関係の処理ができます
アメリカとかだとタイムゾーンが地域によって違うから、パッケージ化するほどの需要あるんですかね。



以下は簡単な例です。

 proc ds2;
 data _null_;
    method init();
       dcl package tz t();
       dcl double utc tokyo having format nldatm20.;
       dcl double tokyo_offset having format time8.;

       /* UTC timeを取得 */
       utc = t.getutctime();
 
       /* Local timeを取得 */
       tokyo = t.getlocaltime('Asia/Tokyo');

       /* Offsetを取得 */
       tokyo_offset = t.getoffset('Asia/Tokyo');

       put utc=;
       put tokyo=;
       put tokyo_offset=;

    end;
 enddata;
 run;
 quit;

ログ
 utc=2018/09/04 11:56:47
 tokyo=2018/09/04 20:56:47
 tokyo_offset= 9:00:00


メソッドの中で「’Asia/Tokyo’」というように地域を指定していますが、タイムゾーンIDといって、「SAS timezone id」とかググれば地域ごとのタイムゾーンIDが載ってるSASのリファレンスが出てくるはずです。

あとは構文自体も大したことないんで、詳細はリファレンスを見てみてください。




とりあえず私は業務で使う事ないんで、暇つぶし用のプログラムを書いて遊んでます。

 proc ds2;
 data _null_;
    method init();
       dcl package tz t();
       dcl double tokyo newyork honolulu vancouver having format nldatm20.;

       tokyo         = t.getlocaltime('Asia/Tokyo');
       newyork    = t.getlocaltime('America/New_York');
       honolulu    = t.getlocaltime('Pacific/Honolulu');
       vancouver = t.getlocaltime('America/Vancouver');

       put tokyo=;
       put newyork=;
       put honolulu=;
       put vancouver=;

    end;

 enddata;
 run;
 quit;

ログ
 tokyo=2018/09/04 20:51:00 
 newyork=2018/09/04 07:51:00
 honolulu=2018/09/04 01:51:00
 vancouver=2018/09/04 04:51:00


適当な地域の現在時刻を調べて「あーニューヨーカーは今頃寝てるのか、いやむしろ寝てないのかな」とか妄想するために使うものだと思っています。
一応、夏時間も考慮されているっぽい(夏時間が存在する地域でちゃんと夏時間の日時になってたんで)




2018年9月2日日曜日

【小ネタ】抽出条件のないWHEREステートメント





以下のように抽出条件のない空のWHEREステートメントを書いてもエラーになりません。

data a;
   set sashelp.class;
   where;
run;

抽出条件が掛かれていないので、すべてのオブザベーションが読み込まれます。




これが出来るからなんなのか、、っていうと、例えば以下のようなマクロを定義したい場合ですね。

* マクロ定義 ;
 %macro test( wh= );

   data a;
      set sashelp.class;
      where &wh;
   run;

 %mend;


* マクロ実行 ;
 %test( wh=age=13 )  /* マクロ実行:抽出条件を指定する場合 */
 %test( wh= )              /* マクロ実行:抽出条件を指定しない場合 */



抽出条件があればマクロ変数whに条件を指定すればいいし、なければ何も指定しなければいいだけ。
抽出条件がある場合とない場合で%ifとか使って分岐処理とかさせる必要ありません。







ただ、where=データセットオプションでは条件を空にするのはダメのようです。

data a;
   set sashelp.class (where=());
run;

ログ
 ERROR: WHERE式の読み込み中に、構文エラーが発生しました。

 ERROR 22-322: 構文エラーです。次のいずれかを指定してください: 名前, 引用符で囲んだ文字列, 
               数値定数, 日時定数, 欠損値, INPUT, PUT.  

 ERROR 76-322: 構文エラーです。ステートメントを無視しました。

 ERROR 6-185: データセットのオプションリストに')'のかっこがありません。

 ERROR 79-322: )を指定してください。

 NOTE: エラーが発生したため、このステップの処理を中止しました。
 WARNING: データセットWORK.Aは未完成です。このステップは、0オブザベーション、
          0変数で停止しました。
 WARNING: このステップを中止したため、データセットWORK.Aを置き換えていません。


ログが怒りすぎ、なんかかわいいです。



なので私は以下のように書いてSASをごまかしています。

data a;
   set sashelp.class (where=(1));
run;

「1」は真(true)の意味です。
常に条件が真(true)の状態、つまり全オブザベーションが読み込まれます。


「0」ってのもあります。

   set sashelp.class (where=(0));


この「0」は偽(false)の意味です。
常に偽(false)の状態、つまり全オブザベーション読み込まれません。



勿論この書き方はwhereステートメントでも通用します。

data a;
   set sashelp.class;
   where 1;
run;