2017年7月31日月曜日

My Favorite SAS Functions (10) CALL SYMPUTX



最後はコールルーチンになりますが、CALL SYMPUTXを紹介します。



構文

  CALL SYMPUTX(  "マクロ変数名" , 変数名  )


・指定した変数の両脇の半角スペースを取り除いたうえで、マクロ変数に格納する。

・数値変数を指定した場合、bestフォーマットを使って文字変換される。
(bestフォーマットに変換した値なので、元の変数値とは異なる (丸め処理が行われる) 場合があることにご注意ください)






それでは、CALL SYMPUTXを使わない場合と、使った場合を比較してみましょう。
以下は、数値変数 X の値をマクロ変数 Y に格納する例です。


Before
data _null_;
   X = 123456;
   call symput("Y", trim(left(put(X,best.))));
run;

%put "&Y";

ログ
"123456"

CALL SYMPUTの中で、「trim(left(put(X,best.)))」 として、
bestフォーマットで文字変換してから余計な両脇の半角スペースを取り除く処理をしていますが、なんて面倒なんだって感じですね。


以下、CALL SYMPUTX を使うとスッキリとした文になります。

After
data _null_;
   X = 123456;
   call symputx("Y",X);
run;

%put "&Y";

ログ
"123456"



📝ちなみに

CALL SYMPUT / SYMPUTX は以下記事で紹介済みですが、数値が丸められる話や、「ローカル・グローバルマクロ変数」の概念によってミスしがちな話など、詳しい挙動を書いているので是非こちらも参照下さい。



以上、過去記事の焼き直しみたいな記事が続いてしまいましたが、
それだけ便利かつアイディア次第で色々できる関数たちなので再度紹介してきました。

色々使い方考えるの楽しいので、SASプログラムを楽しむ人達が増えるといいなぁ。



記事一覧

1.CATS関数
10.CALL SYMPUTX

2017年7月27日木曜日

My Favorite SAS Functions (9) CALL MISSING



第9回目は、関数じゃなくてコールルーチンになりますが、CALL MISSINGを紹介。
指定した変数をすべて欠損値にする機能を持っています。


こちらもやっぱり過去記事で紹介済みです。
指定した変数をすべて欠損値にする【CALL MISSING】



さて、CALL MISSINGの使用前・使用後を見てみましょう。




以下のようなデータセットがあったとします。

data DT1;
   X1 = 123;
   X2 = 456;
   X3 = "abc";
run;
  X1  
  X2  
  X3   
 123 456  abc

ここで、変数 X1, X2, X3 を欠損値にしたいします。

普通に書くと以下のような感じですね。

Before
data DT2;
   set DT1;
   X1=.;
   X2=.;
   X3="";
run;
  X1  
  X2  
  X3  
   .   .  

数値変数だったら「数値変数=.;」
文字変数だったら「文字変数="";」
みたいな感じで書き方分けなきゃいけないし、面倒ですよね。

CALL MISSINGを使えば、もっと楽になります。

After
data DT2;
   set DT1;
   call missing(X1, X2, X3);
run;
  X1  
  X2  
  X3  
   .   .  

📝ちなみに

通常のデータセット以外で使用すると、WARNINGが出て機能しない事があるらしい?ので、ログとかも確認するようにして下さい

2017年7月25日火曜日

そのマクロ変数、ローカル?グローバル?②%LET編




%LETでマクロ変数を定義した時に、ローカル・グローバルどちらになるのか説明します。
まずは以下がSAS内部の判定方法なのでご覧ください。






上の図を整理すると、、マクロ変数を定義する場所によって以下の動作をします。

マクロの外
・「グローバル」になる

マクロの中
・まず、同名のマクロ変数が既に定義されていないかチェックする。
・チェックする順は、「ローカル」→「グローバル」の順
・既に定義済の場合は、上書きする。
・「ローカル」にも「グローバル」にも定義済じゃない場合は、「ローカル」に新規作成。



では具体例でみていきましょう。
まず今回の解説で使うマクロ変数を予めリセット(削除)しときます。

%symdel MAC1 MAC2 MAC3 / nowarn;





動作確認


① マクロ外で定義したマクロ変数が、「グローバル」になる例。

%let MAC1 = abcd;
%put _user_;

ログ
GLOBAL MAC1 abcd



② マクロ内で定義したマクロ変数が、「ローカル」になる例。

%macro TEST(  MAC2 );
       %let MAC2 = 1234;
       %put _user_;
%mend;

%TEST( abcd );

ログ
TEST MAC2 1234

1つ補足ですが、マクロの引数として定義したマクロ変数は、必ず「ローカル」になります。
つまり、「%macro TEST(  MAC2 )」でローカルマクロ変数「MAC2」を定義しています。

次に「%let MAC2 = 1234」で、上記で既に定義した同名のローカルマクロ変数を上書きしています。



③ マクロ内で定義したマクロ変数が「グローバル」になる例

%let MAC1 = abcd;

%macro TEST;
   %let MAC1 = 1234;
   %put _user_;
%mend;

%TEST;

ログ
GLOBAL MAC1 1234

同名のグローバルマクロ変数が既に定義済なので上書きします。



④ マクロ内で定義したマクロ変数が、「ローカル」になる例。

%macro TEST;
       %let MAC3 = abcd;
       %put _user_;
%mend;

%TEST;

ログ
TEST MAC3 abcd

同名のマクロ変数がローカルにもグローバルにも定義済じゃないので、ローカルマクロ変数が作成されます。




次回はCALL SYMPUTによるローカル・グローバルの判定方法を紹介します。



記事一覧

1. 基本概念
2. %LET編
3. CALL SYMPUT編
4. マクロ変数の展開
5. マクロ変数の作成場所を明示的に指定する

2017年7月21日金曜日

My Favorite SAS Functions (8) IFN / IFC関数



第8回目は、IFN / IFC関数。
IFステートメントの関数バージョンみたいなやつです。

これも大変便利なのでヘビーに使う関数のひとつですね。



構文

   IFN (  条件式  , 条件式が真(TRUE)の場合の戻り値 ,  条件式が偽(FALSE)の場合の戻り値 )


戻り値を数値で返したい場合はIFN関数を使い、文字値で返したい場合はIFC関数を使います。


以下記事ですでに紹介済みなので、まずはそちらをご覧ください。
IFN / IFC関数と謎の第4引数



では、IF関数を使わない場合と、使う場合とでプログラムを比較してみます。





例えば、以下のようなデータセットがあったとします。

data DT1;
   length X1 $10.;
   X1="YES"; output;
   X1="NO"; output;
run;

 X1 
   YES  
   NO 


ここで
・X1="YES" だったら「1」
・X1="YES" 以外だったら「0」
みたいな条件分岐で値を設定したいとします。

通常はIFステートメントを使いますよね。

Before
data DT2;
   set DT1;
   if X1 = "YES" then X2=1;
   else  X2=0;
run;
 X1
 X2
  YES      1  
  NO     0  


IFN関数を使えばもっとスッキリとした文になります。

After
data DT2;
   set DT1;
   X2 = ifn(X1="YES",1,0);
run;
 X1 
 X2
  YES      1  
  NO     0




記事一覧

1.CATS関数
8.IFN・IFC関数

2017年7月18日火曜日

そのマクロ変数、ローカル?グローバル?①基本概念




マクロ変数には、以下2種類あるのをご存知でしょうか?

 ローカルマクロ変数


 定義したマクロ内でしか参照できないマクロ変数
 (そのマクロが実行終了すると消去される)

 グローバルマクロ変数 
 
 
 どの場所からでも参照できるマクロ変数
 (ただし、CARDS, DATALINESステートメント内では参照不可




では具体例を見ていきます。
(ただし、どうしてこれがローカルになるの?グローバルになるの?っていうのは別記事で紹介予定なので、今は気にしないでください。)




ローカルマクロ変数の例


以下マクロ「TEST」の中で、ローカルマクロ変数「X」を定義しています。

%macro  TEST;
     %let  X = abcd;
%mend;

%TEST;


ここで以下赤字の%putステートメントを用いて、
マクロ「TEST」の中で、マクロ変数 X の値を展開してみます。

%macro  TEST;
     %let  X = abcd;
     %put  &X;
%mend;

%TEST;

ログ
abcd


問題なくマクロ変数 X の値が展開できている事が分かります。
では次に、マクロの外で展開しようとすると、、

%macro  TEST;
     %let  X = abcd;
%mend;

%TEST;
%put  &X;

ログ
WARNING: Xのシンボリック参照を解決できません。

怒りのWARNINGが出てしまいます。
マクロ内で定義したローカルマクロ変数は、マクロの実行中にしか存在しないので、マクロ外からの展開は出来ません。




グローバルマクロ変数の例


以下では、グローバルマクロ変数「Y」を定義しています。
どこからでも展開することができます。

%let  Y = xyz;
%put  &Y;

%macro  TEST;
     %put  &Y;
%mend;
%TEST;

ログ
xyz
xyz




マクロ変数の表示。


マクロ変数がローカルとグローバルどちらで格納されているのか判断がつかない場合の対処法。

以下 「%put _user_;」で調べる事が出来ます。

%let  Y = xyz;

%macro  TEST;
     %let  X = abcd;
     %put  _user_;
%mend;
%TEST;

ログ
 TEST X abcd
 GLOBAL Y xyz

実際のログには余計なマクロ変数の値が出ますが、上の例ではそれらを除いて分かり易くしてます。
ログの結果から以下が分かります。

・マクロ「TEST」のローカルマクロ変数「X」 には "abcd" という値が格納されている
・グローバルマクロ変数「Y」には "xyz" という値が格納されている


_USER_ 以外にも以下の指定が可能です。

_AUTOMATIC_ … 自動マクロ変数を表示
_GLOBAL_       … グローバルマクロ変数を表示(自動マクロ変数は含まず)
_LOCAL_          ... ローカルマクロ変数を表示(自動マクロ変数は含まず)
_ALL_               … 全てのマクロ変数を表示(自動マクロ変数を含む)
_USER_            … 全てのマクロ変数を表示(自動マクロ変数は含まず)

2017年7月13日木曜日

欠損値の判定【IS NULL】【IS MISSING】【MISSING関数】




WHEREステートメントに、「変数が欠損値」という条件を入れたい場合、以下のように書く方が多いと思います。


・数値変数の場合
  where X = .;

・文字変数の場合
  where X = ””;



別の書き方として、以下のように書くことも出来ます。
  where X is null;        /* is null */
  where X is missing;  /* is missing */
  where missing(X);    /* missing関数 */


変数が欠損値”以外”の場合はnotをつけます。
  where X is not null;        /* is null */
  where X is not missing;  /* is missing */
  where not missing(X);    /* missing関数 */



📝この3つの書き方は

  • 欠損値および特殊欠損値に反応します(特殊欠損値については、あまり使用されていない&それ故に使用すると混乱を招きがちなので、本記事では説明を省略。。)
  • 変数が数値型だろうが文字型だろうが、関係なく通るので便利です
  • ただし「is null」と「is missing」は、WHEREステートメントでした使えない書き方です

IF文とかで使いたい場合は、missing関数が使えます。
  if missing(X) then Y=1;



2017年7月12日水曜日

My Favorite SAS Functions (7) CMISS関数



第7回目は、CMISS関数。
指定した変数のうち、欠損値の数を返してくれます。
おススメポイントが、数値変数・文字変数どちらも指定可能という点です。


基本的な使用例は以下記事で紹介済みなので、そちらをご覧ください。
欠損値のチェックを簡単に行う。



では、CMISSを使わない場合と、使う場合とでプログラムを比較してみましょう。





例えば、以下のようなデータセットがあったとします。

data DT1;
   X1=1;
   X2=.;
   X3="aaa";
run;

 X1 
 X2 
X3
   1    .  aaa 


この変数 X1~X3 のうち、いずれかが欠損値の場合、変数Yにフラグ「1」を立てたいとします。
まずはCMISSを使わない場合。

Before
data DT2;
   set DT1;
   if X1=. or X2=. or X3="" then Y=1;
run;
 X1 
 X2 
X3
 Y 
   1    .  aaa   1  


そしてCMISSを使う場合。

After
data DT2;
   set DT1;
   if cmiss(X1,X2,X3)>0 then Y=1;
run;
 X1 
 X2 
X3
 Y 
   1    .  aaa   1  


今回の例だとCMISSを使った成果が見えづらいですが、変数の数が多いと非常にスッキリとした文になります。


CMISSは便利なのに知名度が低いので、すごい勿体ない。




記事一覧

1.CATS関数
7.CMISS関数

2017年7月4日火曜日

【PROC COPY】データセットを他のライブラリに一括コピー




PROC COPYでデータセット, ビュー, カタログ等のSASデータをコピーする事が出来ます。


📝
ただし「システムオプション等の環境を変更せずに、通常のライブラリから通常のライブラリにSASデータセットをコピー」する分には問題なさそうですが、それ以外では何やら沢山の制限や注意点があるっぽいので、リファレンスをご確認下さい。



構文


   PROC COPY
       IN                =   コピー対象のライブラリ
       OUT            =   出力先のライブラリ
       MEMTYPE  =   (コピー対象のデータのタイプ) ;

       SELECT     コピー対象のデータ ;
       EXCLUDE  コピー対象外のデータ ;
   RUN;


  • MEMTYPE = には以下などが指定可(一部)
  • DATA          …    データセット
    CATALOG   …   カタログ
    VIEW          …    ビュー
  • SELECT・EXCLUDEステートメントを省略すると「MEMTYPE=」に指定したタイプの全データがコピー対象になる
  • 出力先に同名のデータが存在する場合は、上書きされる。




では例を見ていきましょう。
まずは適当にコピーするデータセットを準備。

data DT1 DT2 DT3;
  A=1;
run;



例① WORK の全データセットを MYLIB にコピー
libname MYLIB "C:\TEST";

proc copy in=WORK out=MYLIB memtype=(data);
run;


例② WORK のデータセット DT1,DT2 を MYLIBにコピー
proc copy in=WORK out=MYLIB memtype=(data);
  select DT1 DT2;
run;


例③ WORK のデータセット DT3 以外の全データセット を MYLIBにコピー
proc copy in=WORK out=MYLIB memtype=(data);
  exclude DT3;
run;