Hash Objectsを使用してバイナリフラグをカウント

Hash Objectsネタです。

前にも書きましたがHash ObjectsはSASデータセットをキーとデータの単位でデータ構造を持つことができます。既存のSASデータセットの変数をキーにカウントすることはPROC SQL、DATA Stepでも可能ですがHash Objectsのadd()、replace()メソッドを使用することでPDVにない変数をキー、データとして同オブジェクトのホスト変数に動的に追加しカウントをとることができます。例えば以下のケースでも採番が可能になります。

 

1. クレジットカードの利用額が限度額を超えないイベントをカウントしたい。

2. しかし一回目の限度額を超えないイベントはカウントしない

3. 1、2の条件を判定する変数はデータセットに存在しない

 

データは下のサンプルデータを使用します。price_markが限度額、priceが利用額です。

1オブザベーション目、2オブザベーション目は限度額を超えないのでカウント1,2となりますが、2の条件に当てはまるのでカウントしません。カウントするのは7、8、9オブザベーションからとなります。この処理をIDグループごとに行います。

 

データ

 

data have;

       input @1 item @4 id @8 price_mark @13 price;

       datalines;

1  234 1000 400

2  234 1000 450

3  234 1000 1000

4  234 1000 1000

5  234 1000 1000

6  234 1000 1000

7  234 1000 760

8  234 1000 430

9  234 1000 500

10 234 1000 1000

11 234 1000 1000

12 234 1000 500

13 234 1000 360D

3  321 500  420

4  321 500  500

5  321 500  500

6  321 500  500

7  321 500  500

8  321 500  300

9  321 500  450

10 321 500  300

;

run;

 

Hash Objectで考えると

1. 利用額が限度額を超えるまでのイベントをbooleanフラグで判定する変数を宣言する

2. 1のフラグをカウントする変数を宣言する

3. 1,2の変数をHASH objectのキーとして設定する 

4. データセットを読み込んでキーの存在チェックを行い、存在しない場合は2の変数を1増分してHash Objectsに代入する

5. 一回目のフラグはカウントしないのでIF文で不明値を代入

6. 5の条件以外でフラグがtrueの場合にカウントを実行する

7. 6の条件に当てはまらないオブザベーションは不明値を入力する

 

4のステップでキーの存在チェックとHash Objectsへのキーの挿入を同時に行うことでデータステップでよく使用するLAG関数を使用した面倒なロジックを排除することができます。一見ロジックが多くまどろっこしい印象を受けますが、ステップ3,4のフラグ変数をグループとして動的にHash Objectに定義して処理できることを覚えてしまうと今後のデータステップのコーディングが楽になるかもしれません。

 

data want;

if _N_=1 then do;

       dcl hash h();

*3;

       h.definekey("id","_iorc_","_flg");

       h.definedone();

end;

do until(last.id);

       set have;

       by id;

*1;

       _iorc_=(price_mark ne price);

*2,4;

       if h.check() ne 0 then do;

              _flg+1;

              h.replace();

              if first.id then _flg=1;

       end;

*5;

       if _iorc_=1 and _flg=1 then flg=.;

*6;

       else if _iorc_=1 then flg+1;

*7;

       else if _iorc_=0 then flg=.;

       output;

end;

h.clear();

drop _flg;

run;

 

出力結果

f:id:essbase:20201221135603p:plain