2019年2月1日金曜日

FIRSTOBSオプションの落とし穴




今回は以下2つの記事に関連した内容です。

FIRSTOBS=, OBS=, WHERE を組み合わせたときの挙動
行削除の落とし穴



では本題。まずは適当にサンプルデータ。

data dt1;
  do x="a","b","c";
    output;
  end;
run;


1行目をSQLプロシジャで削除してみます。

proc sql;
  delete from dt1 where x="a";
quit;


すると、削除したオブザベーション番号「1」が欠番になってしまいます(※環境によってここの挙動が異なるかも)
これは上の方で示した2個目のリンク記事で紹介済みですね。
欠番というか、内部でオブザベーションがちゃんと削除されていないのが原因です。



これによって、FIRSTOBS=オプションも影響を受けてしまうようです。
たとえば「FIRSTOBS=2」として読み込んだ場合、、

proc print data=dt1 (firstobs=2);
run;

「x="c"」だけがprintされないとおかしいですよね。
削除したはずの1オブザベーション目が内部ではちゃんと削除されていないからです。


SETしなおせば歯抜けが直るんで、想定通りになります。

data dt1;
   set dt1;
run;

proc print data=dt1 (firstobs=2);
run;



2019年1月30日水曜日

HMS関数で時間値を簡単に作る




HMS関数を使うと、簡単に時間値を作れます。


構文
HMS( 時,  分,  秒 )


例
data DT1;

   * 時 ;
   H   = 20;

   * 分 ;
   M   = 10;

   * 秒 ;
   S    = 05;

   * 時間値を作成 ;
   format TM1 TM2 time10. ;
   TM1 = hms( H, M, 0 );
   TM2 = hms( H, M, S );
run;


H 
M 
S
TM1 
TM2 
  20  
  10  
  05 
  20:10:00  
  20:10:05  


また特定の時間値を作りたい場合は、以下のような書き方が楽。
http://sas-boubi.blogspot.com/2018/03/blog-post.html

data DT2;
   format TM1 time10. ;
   TM1 = '20:10:05't;
run;

2019年1月25日金曜日

ODS EXCELで「セル内改行」されてしまうところを「セル内折り返し」に変える




前回の記事「ODS EXCELで文字変数を「文字列」として出力したい。」に続き、もう1個「ODS EXCEL」で知っといた方がいいオプションを紹介します(※ SAS9.4M5からの機能です)


以下の例をご覧ください。

ods excel file="出力するパスを指定\test1.xlsx";
proc print data=sashelp.cars (obs=5);
  var model / style={cellwidth=90};
run;
ods excel close;


変数MODELについて、幅を縮めてEXCELに出力したところ、幅に合わせてセル内改行されちゃいました。


そこで以下のオプションを追加すると、、

ods excel file="出力するパスを指定\test2.xlsx" options(flow="table");
proc print data=sashelp.cars (obs=5);
  var model / style={cellwidth=90};
run;
ods excel close;


ちゃんと1行で入って、セル内折り返しに切り替わりました!


幅の関係でセル内改行が入ってしまうところを、セル内折り返しにしてくれるオプションです。
(変数値自体に改行が入ってる場合、改行は残ります)



2019年1月24日木曜日

ODS EXCELで文字変数を「文字列」として出力したい。




※今回の内容は、SASやEXCELのバージョン・環境によってうまくいくか未検証なので各時の環境でご確認下さい



「ODS EXCEL」でプロシジャの結果をEXCELに出力できますが、文字変数の書式が崩れるのが問題なんですよね。
例を見ていきます。

* Sample data ;
data test;
input x$;
cards;
001
002
003
.
;



以下は失敗例。

* NG  ;
ods excel file="出力するパスを指定\test1.xlsx" options( flow="tables" );
proc report data=test;
   define x / display;
run;
ods excel close;


*--- test1.xlsx ------------------------------------;


EXCELに出力すると、文字変数の書式が「標準」になってしまう上に、
変数Aは「001」→「1」みたいに数値に変換されちゃいます。



色々調べたところ以下SAS社の出してるProblem Noteにどんぴしゃな説明がありました。
以下は、データの中身(列ヘッダー以外)のセルの書式を「文字列」に設定しています。

* OK ;
ods excel file="出力するパスを指定\test2.xlsx" options( flow="tables" );
proc report data=test;
   define x / display style(column)={tagattr='type:String format:@'};
run;
ods excel close;


*--- test2.xlsx ------------------------------------;
※ A5セルは書式設定が適用できない点だけ注意

  • 「type:String」を入れると「001」のまま出力してくれました、、けどセルの書式が「文字列」になってくれません。実際の見た目とセルの書式が異なってしまい変な感じです。
  • そこで「format:@」を追記すると、「文字列」になってくれました。
  • ちなみに以下の通り、値がないセルは「文字列」になってくれませんでした。



あと、この「type:String」「format:@」の指定の順番を逆にすると環境によっては書式が「文字列」になってくれませんでした。各環境でちゃんと動くか確認が必要です。。



2019年1月18日金曜日

【小ネタ】put _all_で自動変数を出力したくない。




超小ネタです。


「put _all_;」で全変数値をログに出力することが出来ますが、、

data a;
   a=1;
   b="xx";
   c="yy";
   put _all_;
run;

Log:
a=1 b=xx c=yy _ERROR_=0 _N_=1

自動変数(_ERROR_や_N_など)も出力されてしまいます。



そこで、以下で紹介した方法を使うと
https://sas-boubi.blogspot.com/2015/10/put.html

data a;
   a=1;
   b="xx";
   c="yy";
   put (_all_)(=);
run;

Log:
a=1 b=xx c=yy

何故か自動変数は出なくなります。なんでか知らないけど。


あ、今年もどうぞよろしくお願いいたします!



2019年1月11日金曜日

ODS GRAPHICSの設定を保存・復元する。




SAS9.4M3からODS GRAPHICSの設定を一時保存・復元する「PUSH・POPオプション」が追加されました。

本題に入る前に、まずは前提知識として「SHOWオプション」から紹介していきます。




SHOWオプション

ODS GRAPHICS / SHOW ;

  • 現在のODS GRAPHICS の設定をログに表示することが出来ます。
  • SAS9.4M3以降の機能です。

例
ods graphics / show ;



PUSHオプション

ODS GRAPHICS / PUSH ;

  • 現在のODS GRAPHICSの設定を一時保存することが出来ます。
  • SAS9.4M3以降の機能です。
  • PUSHオプションを指定する度に、その時点のODS GRAPHICSの設定を別々に保存することが出来ます。


例
/*** ① 現在のODS GRAPHICSの設定を見てみる ********/
ods graphics / show;

/* 設定を保存 */
ods graphics / push;



/*** ② ODSで出力される画像の幅を300pxに変更 ********/
ods graphics / width=300;
ods graphics / show;

/* 設定を保存 */
ods graphics / push;





POPオプション

ODS GRAPHICS / POP ;

  • 一時保存したODS GRAPHICSの設定を呼び出すことが出来ます。
  • SAS9.4M3以降の機能です。
  • POPオプションを指定する度に、PUSHで保存した設定の新しい方から順に呼び出されます。
  • つまり、PUSHで設定①、設定②、設定③と3回設定を保存した場合、POPでは設定③、設定②、設定①という順で呼び出される(スタックの原理)


例
/* 設定の呼び出し */
ods graphics / pop;
proc sgplot data=sashelp.class;
  scatter x=height y=weight;
run;

/* 設定の呼び出し */
ods graphics / pop;
proc sgplot data=sashelp.class;
  scatter x=height y=weight;
run;





役に立つ例

汎用マクロを作る際に便利です。以下の例をご覧ください。

%macro test;

  /* 現在のODS GRAPHICSの設定を保存しておく */
  ods graphics / push;

  /* SGPLOT */
  ods graphics / reset=all height=500 width=500;
  proc sgplot data=sashelp.class;
       scatter x=weight y=height;
  run;

  /* マクロ実行前のODS GRAPHICSの設定に戻す */
  ods graphics / pop;

%mend;

  • マクロの最初にPUSH、最後にPOPを置いています。
  • これにより、いくらマクロの中でODS GRAPHICSの設定をいじっていても、マクロ実行後には設定を元に戻すことが出来ます。


2018年12月28日金曜日

SASで雪だるまを描く




2018年も本ブログを見て頂いた方、コメントしてくださった方、どうもありがとうございました!
来年もどうぞよろしくお願いいたします!!

SASでグリーティングカードを作ってみました。


以下が今回作ったプログラムです。SAS9.4以降で動作します。
*** 描画用データ作成 ;
data SNOW;
  * ゆきだるま描画用データ作成 ;
  retain x1  0  y1  0;
  retain x2  0  y2 -6.5;
  retain x3 -1  y3 1;
  retain x4  1  y4 1;
  retain x5  0  y5 0;
  retain x6  0  y6 0.5;
  retain x7  0  y7 5.5;
  retain x8  0  y8 7;

  * ゆき描画用データ作成 ;
  call streaminit(777);
  do scene=1 to 5;
     do snow_x = -10 to 10 by 1;
        snow_y = rand('uniform')*30-15;
        output;
     end;
  end;
run;

*** 描画 ;
title ;
options  ANIMATION=START  ANIMDURATION=1   PRINTERPATH=GIF ;

ods noresults;
ods printer file="出力するパスを指定\test.gif";
ods graphics on / height=4in width=4in;

%macro ANIMATION;
  %do i=1 %to 5;
  proc sgplot data=SNOW noautolegend;
     where scene=&i;
     styleattrs wallcolor=skyblue;
     symbolchar name=SNOW char='2744'x;
     scatter x=snow_x y=snow_y /  markerattrs=(symbol=SNOW  size=1.5cm color=white);
     scatter x=x1 y=y1  /  markerattrs=(symbol=circlefilled  size=3cm color=white);
     scatter x=x2 y=y2  /  markerattrs=(symbol=circlefilled  size=4cm color=white);
     scatter x=x3 y=Y3  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
     scatter x=x4 y=Y4  /  markerattrs=(symbol=circlefilled  size=0.2cm color=black);
     scatter x=x5 y=y5  /  markerattrs=(symbol=ArrowDown  size=0.5cm color=black);
     scatter x=x6 y=y6  /  markerattrs=(symbol=TriangleDownFilled  size=0.3cm color=orange);
     scatter x=x7 y=y7  /  markerattrs=(symbol=TriangleFilled  size=1.2cm color=red);
     scatter x=x8 y=y8  /  markerattrs=(symbol=CircleFilled  size=0.6cm color=white);
     inset "Happy Holidays"  /  position=top textattrs=(color=green size=35cm family='Arial');
     xaxis min=-3 max=3  display=none;
     yaxis min=-5 max=1  display=none;
  run;
  %end;
%mend;

%ANIMATION;

ods graphics on / reset=all;
ods printer close ;
ods results;

options  ANIMATION=STOP ;