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

2017年5月15日月曜日

My Favorite SAS Functions (3) WHICHN / WHICHC関数


第3回目は、一番お気に入りの WHICHN / WHICHC関数です。
お気に入りすぎて、WHICHN関数使ってる夢みたことあります。



構文


    WHICHN( Y , X1 , X2 , X3 … )


・Yと同じ値がXの何番目に初登場するか返す。
・Yと同じ値がXに無い場合、0を返す。
・Yが欠損値の場合、欠損値を返す。
・引数に数値型の変数または値を指定する場合はWHICHN関数を用いる。
・引数に文字型の変数または値を指定する場合はWHICHC関数を用いる。





以下のように、Y の値が X1~X3 の何個目と同じか知りたいとします。

  Y  
  X1  
  X2  
  X3  
  XNUM  
  bb    aa  bb  cc     2


以下、WHICHC関数を使わない場合(Before)と、使う場合(After)。

Before
  if Y = X1 then XNUM=1;
  else if Y = X2 then XNUM=2;
  else if Y = X3 then XNUM=3;


After
  XNUM = whichc( Y ,X1,X2,X3 );



過去記事でもとりあげてるので、是非読んでみてください。


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関数を使うやり方と同様。

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


注意点

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



2014年3月28日金曜日

1行プログラムその4:カテゴリ変数の作成



今回は1行でカテゴリ変数 (数値) に置き換える方法。

[年齢]
20歳未満               → 1
20歳以上30歳未満 → 2
30歳以上               → 3


サンプルデータ

data DT1;
input AGE;
cards;
17
23
19
37
27
;

データセットDT1
AGE
17
23
19
37
27

求めたい結果
AGE  AGEGRP
17       1
23       2
19       1
37       3
27       2




1行で書く方法。

普通に書くとこんな感じですが、
data DT2;
   set DT1;
   if  0   <   AGE <20      then  AGEGRP = 1 ;
   if  20 <= AGE <30      then  AGEGRP = 2 ;
   if  30 <= AGE            then  AGEGRP = 3 ;
run;


WHICHN関数で1行でいける。
data DT2;
  set DT1;
  if AGE^=. then AGEGRP = whichn(1, 0<AGE<20, 20<=AGE<30, 30<=AGE);
run;


  • WHICHN関数の構文は「whichn(Y, X1,X2…)」で、Yと同じ数値がXの何番目に初登場するか返してくれます。
  • Yと同じ数値がどのXにもない場合「0」が返されます。
  • Yが欠損値の場合、欠損値が返される。
  • リンクさせて頂いてる「データステップ100万回」の「whichn関数はwhereステートメントでも使える話とその応用をだらだら」で最後に提案されてるアイディアに再インスパイアされて今回の問題に当てはめて利用させて頂きました。


今回の使用法の注意点

・カテゴリ値が1~5くらいまでならいいけど、「年齢=NULL → 100」とか飛び離れたカテゴリ値を設定したい場合、関数の引数を100個指定しなきゃいけなくなるので実用的じゃなくなる → whichn(Y, X1,X2…X100)


2014年3月1日土曜日

IN=オプションとWHICHN関数のコンボ技。




ちょっとしたコンボ技を紹介。

複数のデータセットをSETして1つにまとめた時、
どのデータセットから持ってきたレコードなのか識別するために由来コードを振ることがあって、そういった時に使えます。


サンプルデータ作成

data DT1;
  do V=1 to 2;
     output;
  end;
run;

data DT2;
  do V=3 to 4;
     output;
  end;
run;

データセット「DT1」
V
1
2

データセット「DT2」
V
3
4




コンボ技

上記データセットを縦結合して、
・「DT1」由来のレコードであれば「ORIGIN=1」
・「DT2」由来のレコードであれば「ORIGIN=2」
というコードの変数を作りたいとします。

求めたい結果
V   ORIGIN
1      1
2      1
3      2
4      2



最近までこんな感じで書いてましたが、、
data OUT2;
   set DT1 (in=_IN1)
         DT2 (in=_IN2)
   ;
   if  _IN1=1 then ORIGIN = 1;
   if  _IN2=1 then ORIGIN = 2;
run;



WHICHN関数を組み合わせると、以下のように書けます。
data OUT2;
   set DT1 (in=_IN1)
         DT2 (in=_IN2)
   ;
   ORIGIN = whichn(1,_IN1, _IN2) ;
run;

結合するデータセットがいくつあっても1文で書けちゃうので楽。


WHICHN関数の構文は「whichn(Y, X1,X2…)」で、Yと同じ値がXの何番目に初登場するか返してくれます。
・YとXは数値型の変数または値である必要があります
・Yと同じ値がXにない場合、0が返される
・Yが欠損値の場合、欠損値が返される