2016年2月18日木曜日

グループ毎に空白行を追加したい



やりたい事

* サンプルデータ ;
data DT1;
length NO SEX $10. AGE HEIGHT 8.;
input NO$ SEX$ AGE HEIGHT @@;
cards;
001 F 25 159.2  002 F 43 161.8  003 F 21 158.1  004 M 19 178.0  005 M 28 160.2
;



変数SEXの値ごとに1行だけ空白行を追加したいとします。




方法① データステップ

proc sort data=DT1;
   by SEX ;
run ;

data OUT1;
   set DT1 ;
   by SEX ;
   output ;
   if last.SEX then do ;
       call missing( NO, AGE, HEIGHT );
       output ;
   end ;
run ;


ざっくり解説すると、
  • output;」でいったん現在のオブザベーションをデータセットに出力
  • if last.SEX then do;」で、SEXの値「F」「M」ごとに最後のオブザベーション(3obsと5obs)を読み込んだ時に、
  • call missing( NO, AGE, HEIGHT )」で変数NO, AGE, HEIGHTを欠損値にして、
  • output;」でデータセットに再出力しています。


📝注意点

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





方法② REPORTプロシジャ

proc report data=DT1 out=OUT2 nowd ;
   define _numeric_  / display ;
   define SEX  / order order=internal missing ;
   break after SEX  / ;
run ;


REPORTプロシジャってデータセットにも出力できるんです!

  • define SEX / order order=internal missing;」と「break after SEX /;」で、SEX毎に要約行を追加
    • この書き方、HTML等への出力時には要約行が入らないんですが、データセット出力時には要約行が入ります
  • このままだと要約行に数値変数AGE, HEIGHTの要約値(合計)が入ってしまうので、「define _numeric_ / display;」で全数値変数を集計せずただdisplayするだけ(表示するだけ)にしています(データセット中に数値変数が存在しないなら「define _numeric_ / display;」は不要)
  • out=OUT2」でデータセットOUT2に出力


他に何かいいアイディアがあれば教えてください!


3 件のコメント:

  1. こんにちは。
    空白行の挿入ではなく、オブザベーションのコピーをする方法をご存じないでしょうか…?
    任意の変数に、任意の値があったとき、そのオブザベーションだけコピーしたいのです。

    返信削除
    返信
    1. かんなさん
      こんにちは。コメントありがとうございます。

      おそらく、outputステートメントで実現できそうです。
      前提知識と注意事項として、まずは以下の記事をご覧ください。
      https://sas-boubi.blogspot.com/2015/10/output.html

      そして、以下が例になります(やりたい事あっていますか?)

      /*** テストデータ ********/
      data have;
      input a b;
      cards;
      1 111
      2 222
      3 333
      ;

      /*** outputステートメントの例 ********/
      data want;
      set have;

      /* outputする */
      output;

      /* a=2の時、もう1度outputする */
      if a=2 then output;

      run;

      削除
    2. 1つ前のコメントにoutputステートメントに関する記事のリンクを載せましたが、

      その記事にあるようにoutputステートメントは応用がきく半面、内部の動きを知っていないと、想定外の結果になってしまいがちなのでご注意下さい。
      (特に、データステップ内でoutputステートメントを記述する位置や、他のステートメントとの組み合わせなどで罠にハマりやすいです)

      不明点がありましたら、またコメント頂ければと思います。

      削除