ラベル ステートメント: SUM の投稿を表示しています。 すべての投稿を表示
ラベル ステートメント: SUM の投稿を表示しています。 すべての投稿を表示

2014年5月28日水曜日

色々な例数を簡単に出す2



「色々な例数を簡単に出す」のデータステップ編です。



サンプルデータ
data DT1;
  label  FOOD     = "購入食品"
          PRICE    = "価格"
          EATFLG = "食べたフラグ"
  ;
  length FOOD $20.;
input  FOOD$  PRICE  EATFLG;
cards;
ジュース  150  1
カップ麺  100  .
ジュース  100  1
ジュース  200  .
カップ麺  200  .
;



求めたい結果
 購入数  ジュース購入数  カップ麺購入数  
  5  3    2



データステップで各例数を計算
data DT2;
   set DT1 end=EOF;           /* ① */

   C1 + (FOOD^="") ;          /* ② */
   C2 + (FOOD="ジュース") ;
   C3 + (FOOD="カップ麺") ;

   if  EOF;                         /* ③ */
   keep C:;
run;



解説
前に紹介した「SUMステートメント入門」と「1行プログラミング6:TRUE/FALSEを計算に利用する。」の合わせ技です。

  • ① まず「end = 一時変数名」と書くと、最終行の一時変数に1が入ります。
  • ② 条件式によって返される「1.true」「0.false」をSUMステートメントで合計していきます。
  • ③ 最終的な合計がでる最終行のみを残します。






応用
グループ毎に色々な例数や合計を出すこともできる。

たとえば、サンプルデータで以下のように「食品毎の例数や合計」を出したいとする。
 食品  購入数  合計金額   食べた食品の合計金額 
 カップ麺 2   300 0
 ジュース 3   450 250


データステップでグループ毎の例数や合計を出す。
proc sort data=DT1; by FOOD; run;

data DT3;
   set DT1;
   by FOOD;
   if first.FOOD then call missing(C1,C2,C3);   /* ① */

   C1 + (FOOD^="");                                 /* ② */
   C2 + PRICE;
   C3 + (EATFLG=1)*PRICE;

   if last.FOOD;                                        /* ③ */
   keep FOOD C:;
run;



解説
  • ① グループの各先頭行の時、計算結果を入れる変数を初期化する(call missingでNULLにする)
  • ② SUMステートメントで合計していきます。
  • ③ グループ毎の最終行のみを残します。


「C3 + (EATFLG=1)*PRICE;」のところの仕組みを補足しておくと、 (EATFLG=1) の条件が
  • 「0.false」なら、C3 + 0*PRICEとなり、
  • 「1.true」なら、C3 + 1*PRICEとなり、
「true/false」によって合計に含めるかどうかのトリガーにしています。



📝注意点

今回のテクニックの中で使用している「END=オプション」「FIRST.BY変数」「LAST.BY変数」は「サブセット化IF」と一緒に使用すると正しく動かなくなる事があります。



2014年5月26日月曜日

Sumステートメント入門



「Sumステートメント」または「合計ステートメント」とも言いますが、
どいうものかは説明よりプログラムを見てしまったほうが早いかも。


*** サンプルデータ作成 ;
data DT1;
    A=.   ;  output;
    A=10 ;  output;
    A=20 ;  output;
run;

 A 
  . 
 10
 20 

*** Sumステートメントを使う ;
data DT2;
    set DT1;
    NO + 1;
    A2 + A;
run;

 A   NO   A2 
  .    1     0 
 10   2  10
 20    3   30 



解説

変数名 + 足す値 ;

このイコールを省略した書き方がSumステートメントです。
変数の値を次レコードにも保持してくれて、どんどん足し合わせていくことができます。


注意点として、データステップ内でSumステートメント用の変数を新たに用意して、その変数にSumステートメントを行ってください。
仕組み上、データセットに既に存在している変数だとSumステートメントがうまく動作しません。



サンプルでは以下の動きをしています。
・「NO+1」は、変数NOに対して上から順に1を足していってます。
・「A2+A」は、変数A2に対して上から順に変数Aの値を足していってます。



ちなみに、RETAINを使って以下のように書いたときと同等です。

data DT2;
    retain NO A2 0;
    set DT1;
    NO = sum(NO,1);
    A2 = sum(A2,A);
run;



2013年12月27日金曜日

グループ内連番をふる方法。


グループ内連番をふる機会はすごく多いと思うので、まとめてみました。


サンプルデータ

data DT1;
input SUBJID$ V$;
cards;
001 a
001 b
001 c
002 x
002 y
;


求めたい結果
「SUBJID」毎に「V」の順番で連番をふる。





データステップで連番をふる

*** 方法1 **********;
proc sort data=DT1; by SUBJID V; run;

data OUT1;
  set DT1;
  by SUBJID V;

  if first.SUBJID then SEQ=0;
  SEQ+1;
run;

*** 方法2 **********;
proc sort data=DT1; by SUBJID V; run;

data OUT1;
  set DT1;
  by SUBJID V;

  SEQ+1-first.SUBJID*SEQ;
run;


・方法1が一般的なやり方だと思う。
・方法2は仕組みを理解すれば1行で書けるのでおススメ。


📝注意点

今回のテクニックの中で使用している「FIRST.BY変数」は「サブセット化IF」と一緒に使用すると正しく動かない事があります。
(解説記事:「サブセット化IFでありがちな落とし穴」)