DATEKEYSプロシジャを使って日付にイベントを関連付ける(なんか凄い応用効く予感)

SASにはholidayname関数、holidaycount関数、その他holidayから始まる
たくさんの関数があります。それらは日付や期間を与えることで祝日の名前や祝日の数を
返したりする機能を持っているのですが…

試しに11月11日を与えて、そこに定義されている祝日の名前を書きだしてみます

data _null_;
dt='11NOV2016'd;
do count= 1 to holidaycount(dt);
name=holidayname(dt,count);
put dt yymmdds10. +2  count= name= ;
end;
run;






と、なんか3つでてきましたね
ちなみに
VETERANS : 退役軍人の日 11月11日
VETERANSUSG : 退役軍人の日(米国政府の祝日)
VETERANSUSPS : 退役軍人の日(米国郵政公社の祝日)
らしいです。

要するに、対応しているのが米国の祝日なんですね。
日本じゃ使い道ね~、工数計算とかスケジュールをSASで作るときに使えたら楽なのに~ってずっと思ってました。
ところが9.4で試用版として導入されたproc datekeysを使うことで話は変わってきます。

proc datekeysは結構深いプロシジャのようなのですが、今回は一番単純に使ってみます

2016年の祝日を直打ちで設定(データセットからも流し込める)して
それを使って5月の祝日判定をしてみましょう

まずdatekeysプロシジャを使って、イベント日の定義情報をデータセット化します

proc datekeys;
   /*元日*/ datekeydef New_Years_Day= '1JAN2016'd / pulse=day;
   /*成人の日*/ datekeydef Coming_of_Age_Day= '11JAN2016'd / pulse=day;
   /*建国記念の日*/ datekeydef National_Foundation_Day= '11FEB2016'd / pulse=day;
   /*春分の日*/ datekeydef Vernal_Equinox_Day= '20MAR2016'd / pulse=day;
   /*振替休日*/ datekeydef Substitute_Holiday= '21MAR2016'd / pulse=day;
   /*昭和の日*/ datekeydef Showa_Day= '29APR2016'd / pulse=day;
   /*憲法記念日*/ datekeydef Constitution_Memorial_Day= '3MAY2016'd / pulse=day;
   /*みどりの日*/ datekeydef Greenery_Day= '4MAY2016'd / pulse=day;
   /*子供の日*/ datekeydef Childrens_Day= '5MAY2016'd / pulse=day;
   /*海の日*/ datekeydef Marine_Day= '18JUL2016'd / pulse=day;
   /*山の日*/ datekeydef Mountain_Day= '11AUG2016'd / pulse=day;
   /*敬老の日*/ datekeydef Respect_for_the_Aged_Day= '19SEP2016'd / pulse=day;
   /*秋分の日*/ datekeydef Autumnal_Equinox_Day= '22SEP2016'd / pulse=day;
   /*体育の日*/ datekeydef Health_Sports_Day= '10OCT2016'd / pulse=day;
   /*文化の日*/ datekeydef Culture_Day= '3NOV2016'd / pulse=day;
   /*勤労感謝の日*/ datekeydef Labour_Thanksgiving_Day= '23NOV2016'd / pulse=day;
   /*天皇誕生日*/datekeydef Emperor_Akihitos_Birthday= '23DEC2016'd / pulse=day;

   datekeydata out=MyHolidays ;
run;

次にeventds=オプションで定義データセットを指定します。ここでnodefaultsも追加しておくと
デフォルトの定義(=アメリカの祝日)を外すことができます。日米両方の祝日をだしたければnodefaultsはいりません。

options eventds=(nodefaults MyHolidays);
data MAYHOLI;
length dt 8. name $50.;
do dt='1MAY2016'd  to '31MAY2016'd ; 
call missing(name);
if holidaycount(dt) = 0 then output;
else do count= 1 to holidaycount(dt);
name=holidayname(dt,count);
output;
end;
end;
format dt yymmdds10.;
keep dt name;
run;






















というわけです(画像は途中まで)。
ちなみにイベントデータは、週単位や月単位、あるいは幅を持って設定もできますし、
リファレンス見てるともっと色々できそうです。

これ、祝日とか判定する以外にもなんか使えそうじゃないですか?

特に、開始と終了日を与えてその間の祝日回数を数えるHOLIDAYCK関数とか応用できそうじゃないですか?

頭のいい人は何か使い道を編み出して発表してください


3 件のコメント:

  1. SASYAMAさん,こんにちは。いつもためになる記事をありがとうございます。以前,プログラミング掲示板に質問させていただいたTYと申します。少し前から自分の整理ためにブログを作成したのですが,私が質問した内容を自分のブログに引用してよろしいでしょうか(引用先は明示します)。 誰に聞けばよいのかよくわからなかったので,管理人のSASYAMAさんにお伺いしました。

    これからも記事を楽しみにしています。宜しくお願いいたします。

    返信削除
  2. Yamabeさん、こんにちわです。TYさんでしたか!ブログ拝見させていただいてます。
    是非是非!ご自身の投稿でしたらなおのこと、好きに貼っちゃってください。僕のブログ記事や、掲示板のSASYAMAの書き込み等も自由に引用してくださって結構です。
    掲示板の他の方の書き込みについて、そのまま文中に引用されるのは、もしからしたらちょっと微妙かもしれないので、その場合は一応リンク参照にしておいてください。
    SAS掲示板に投稿されている方で、あんまり文句言われる方はいないような気がしますが。

    返信削除
  3. 私のブログをご存知でしたか。誰にも見られていないと思っていたのでちょっと意外でした。
    ありがとうございます。今のSQLの基礎シリーズがひと段落したら応用編として掲載します。基本的に自分のやつしかするつもりはありませんが,もしほかの方の書き込みでいいなと思ったやつにはLINK付で掲載しますね。

    返信削除