ラベル 関数: IFN の投稿を表示しています。 すべての投稿を表示
ラベル 関数: IFN の投稿を表示しています。 すべての投稿を表示

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関数

2016年1月27日水曜日

IFN / IFC関数と謎の第4引数




IFN / IFC関数は、簡単に言うとIFステートメントの関数バージョンです。


構文

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

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






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

*** IFC関数を使ってみる ;
data OUT1;
    set DT1;
    length B $30.;
    B = ifc( A<=10 , "10以下", "10より大きい" );
run;

 10  
 10以下  
  .  
 10以下 
 20
 10より大きい  


Aが欠損値の場合にも「10以下」ってなるのはおかしいよねって感じなので、
その場合、以下のようにIFN / IFC関数をネストさせる方法もありますが、、ネスト増やして見づらくなるんだったら、IFステートメント使った方が良いですね。。

B = ifc(A=. ,"未記載", ifc( A<=10 , "10以下", "10より大きい" ) );

 10  
 10以下  
  .  
 未記載
 20
 10より大きい 



謎の第4引数


実はこの関数、謎の第4引数が存在します。

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


ずっと疑問なんですが、この第4引数ってどういう時に使うんでしょうか?
というのも条件式の結果は、TRUE か FALSE しか返しません。

たとえば上の方のサンプルプログラムでIFC関数に書いた条件式 「A<=10」 に対する真偽は以下のようになります。

・ Aの値が10以下の場合        ・・・ TRUE
・ Aの値が10より大きい場合   ・・・ FALSE
・ Aの値が欠損値の場合        ・・・ TRUE (「10以下」と解釈。)


なんでこの関数だけ3値論理?
ということで、こういう時に使えそうねってアイディアがあれば教えてほしいです。



2015年3月13日金曜日

LAG関数とIFN / IFC関数のコンボ技



LAG関数の挙動には注意が必要です。
以下のプログラムを実行してみて、予想した結果になるか見てみましょう。

*** サンプルデータ作成 ;
data DT1;
   do X = 1 to 5;
      output;
   end;
run;

*** 例1: 2個前の値をとってくる ;
data OUT1;
   set DT1;
   Y = lag2(X);
run;
 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
   
  5
  3  


*** 例2: IFステートメントを含む場合 ;
data OUT2;
   set DT1;
   if X ^= 4 then Y = lag2(X);
run;
 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
   
  5
  2 




例1は予想通りだと思いますが、例2はどうでしょう?
結果の赤文字で示した部分が「3」になると思ってたら要注意です。


解説


ここから、別記事「LAG関数の動き」で紹介したイメージをもとに説明するので、この別記事を読んでいないと分かりづらい部分あるかも。



まずは以下、「Y = LAG2(X)」と書いたときの内部処理のイメージです。
(自分なりの解釈になっている可能性があるかもしれませんので、あしからず・・)

まず、LAG関数によって内部で「キュー」と呼ばれる仕組みを利用しています。





続いて、「if X ^= 4 then Y = lag2(X)」というように、IFステートメントと組み合わせたときの内部処理のイメージ。

(こちらも自分なりの解釈になってる可能性あり)



LAG関数が実行されないと、キューの中身が更新されないことによるものですね。





ここでもし、「IF条件が通った時だけ、2行前の値を取ってきたい」という場合は、以下のようにLAG関数が毎回実行されるように工夫します。

data OUT3;
   set DT1;
   Y2 = lag2(X);
   if X^= 4 then Y = Y2;
   drop Y2;
run;

 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
  .  
  5
  3  



ここからちょっとした裏技を紹介。
上記の処理は、LAG関数とIFN・IFC関数を組み合わせることによって、より簡潔に書くことが出来ます。

data OUT3;
   set DT1;
   Y = ifn( X^=4, lag2(X), . );
run;

 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
  .  
  5
  3  



解説


IFN・IFC関数の構文は以下の通り。

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

 ・・・ 戻り値が数値の場合はIFN、文字の場合はIFC関数を使います。

そしてこの関数、1つ面白い性質があります。

この関数が実行されるとき、
第1引数の条件式の結果がなんであろうと、第2・第3引数は、内部で両方とも処理(計算)が行われているようです。


つまり今回の 「ifn( X^=4, lag2(X), . )」 は、
条件式「X^=4」の結果がTRUEだろうがFALSEだろうが、内部では毎回こっそり第2引数の「lag2(X)」が実行されています。
毎回LAG関数が実行されることで、2行前の値を取ってくることができているわけです。

この性質、他にも使えそうですね。なんか思いつきそうで思いつかないですが。





2014年4月16日水曜日

1行プログラムその5:有無変数

有無変数を1行でつくる方法を紹介。

サンプルデータ作成

data DT1;
length NO $3. ALLERGY $20.;
input NO$ ALLERGY$;
cards;
001 花粉症
002 .
003 猫アレルギー
;
run;

データセットDT1
NO   ALLERGY
001    花粉症
002   
003    猫アレルギー


やりたい事

サンプルに対して、以下の有無変数を作成したい。
【アレルギー有無】
ALLEYN

【導出方法】
アレルギー(ALLERGY)に記載がある場合「2:有」、それ以外「1:無」とする。

欲しい結果
NO   ALLERGY       ALLEYN
001   花粉症               2
002                            1
003   猫アレルギー       2



1行プログラム

*** 有無変数を1行で作るいくつかの方法 ******************;
data DT2;
    set DT1;

    *** 通常のやり方 ;
    if  ALLERGY^="" then  ALLEYN = 2;
    else  ALEEYN = 1;

    *** 方法① 真偽値 ;
    ALLEYN1 = (ALLERGY^="") +1;

    *** 方法② WHICHN関数 ;
    ALLEYN2 = whichn(1,  ALLERGY="",  ALLERGY^="");

    *** 方法③ IFN関数 ;
    ALLEYN3 = ifn(ALLERGY^="",  2, 1);

run; 

解説
--- 方法① ------------
論理式の結果が「1:TRUE」か「0:FALSE」で返されるので、それに+1してやれば有無変数になります。

--- 方法② ------------
このやり方については「こちら」で解説してます。

--- 方法③ ------------
IFN関数の構文は「IFN(論理式,  論理式がTRUEの戻り値,   論理式がFALSEの戻り値)」でEXCELのIF関数に似てる。
ただし返す戻り値が数値の場合はIFN、文字の場合はIFCと使い分ける必要があります。


1行プログラム番外編

有無変数を「NO、YES」と文字で持たせたい場合は以下のようになります。

data DT2;
    set DT1;
 
    length ALLEYN4 ALLEYN5 $10.;

    *** 方法① IFC関数 ;
    ALLEYN4 = ifc(ALLERGY^="",  "YES",  "NO");

    *** 方法② CHOOSEC関数 ;
    ALLEYN5 = choosec((ALLERGY^="")+1,  "NO",  "YES");

run;

解説
--- 方法① ------------
前述したIFN関数を使うやり方と同様。

--- 方法② ------------
真偽値と「こちら」で紹介したやり方をミックスした方法です。


注意点

今回紹介した方法は、有無の条件が排反である場合に限ります。
(有無が「有」になる条件以外すべて「無」になるような裏と表の関係)