2017年6月8日木曜日

変数に含まれる特定の文字の数をカウントする:COUNT関数編




例えば「this is a pen」という文字列に「is」という文字が何個含まれるかカウントしたいような場合、COUNT系関数が使えます。



COUNT、COUNTC関数


シングルバイト(半角の英数など)の文字を対象とする場合、上記2つの関数を状況によって使い分ける
(わりと気難しい関数なので、後段の解説や注意点も参照下さい)

data DT1;
     A  = "this is a pen" ;
     B  = count( trimn(A) , "is" );
     C  = countc( trimn(A) , "isp" );
run;
  A  
  B  
  C  
  this is a pen    2  5

📝関数に指定した変数は、場合によって上記のように「TRIMN関数」で包む必要があります。理由はあとで解説します



解説

COUNT( trimn(A) , "is")
第2引数の "is" という文字列が変数Aに何個あるかを返す(見つからなかった場合は0を返す。)

ただし、カウントする文字の出現位置が重なっている場合、、
例えば「count( "PenPenPen", "PenPen" )」みたいなやつは、関数の結果が「1」か「2」どちらかになる可能性があって挙動が怪しいようなので注意。


COUNTC( trimn(A) , "isp" )
第2引数の "isp"を一字ずつ分解し、「i」「s」「p」という文字が変数Aに何個あるかを返す(見つからなかった場合は0を返す。)



注意点
  • 日本語などのマルチバイト文字を含む場合は、以下記事の通りうまく動作しないのでご注意ください。
  • 以下で解説している問題がCOUNT関数にもあるので、場合によって「TRIMN関数」を併用する必要があります。
    • 文字値の末尾にある空白問題
    • 上記リンク記事で解説している通り、変数値の長さがLENGTHより短い場合、末尾に半角スペースが入るので、以下のように想定外の結果を返す場合があります。

/* 失敗例 */
data DT1;
     length A $20.;
     A  = "this is a pen" ;
     B  = count( A , " " );
     C  = countc( A , " " );
run;
  A  
  B  
  C  
  this is a pen   10 10


てことで「TRIMN関数」で一時的に末尾の半角スペースを取り除いてやります。

/* 成功例 */
data DT1;
     length A $20.;
     A  = "this is a pen" ;
     B  = count( trimn(A) , " " );
     C  = countc( trimn(A) , " " );
run;
  A  
  B  
  C  
  this is a pen    3  3




KCOUNTX、KCOUNTC関数(SAS9.4M5から)


マルチバイト(日本語などの全角文字など)を含む文字を対象とする場合、頭に”K”がつく上記2つの関数を使います
(こちらも気難しい関数なので、後段の解説や注意点も参照下さい)

data DT2;
     A  = "わたしはペンギンではありません" ;
     B  = kcountx( trimn(A) , "ペン" );
     C  = kcountc( trimn(A) , "はン" );
run;
  A  
  B  
  C  
  わたしはペンギンではありません    1  4

📝COUNT関数のところでも解説した通り、関数に指定した変数は、場合によって「TRIMN関数」で包む必要があります。



解説

KCOUNTX( trimn(A) , "ペン")
第2引数の "ペン" という文字列が変数Aに何個あるかを返す(見つからなかった場合は0を返す)

ただし、カウントする文字の出現位置が重なっている場合、、
例えば「kcountx( "ペンペンペン", "ペンペン" )」みたいなやつは、関数の結果が「1」か「2」どちらかになる可能性があって挙動が怪しいようなので注意。

あと間違えやすいですが、KCOUNTではなく、KCOUNTXです(KCOUNTは全く別のことをやる関数です)


KCOUNTC( trimn(A) , "はン" )
第2引数の "はン"を一字ずつ分解し、「は」「ン」という文字が変数Aに何個あるかを返す(見つからなかった場合は0を返す)



注意点

本当にどんな仕様だよって感じなんですが、
第1引数がシングルバイトの文字のみで構成されている場合、マルチバイト非対応の関数に変化して間違った結果を返す場合があります。

例えばshift_jis環境で以下を実行すると、、
  • 「kcountc( "\", "表" )」→ 第1引数がシングルバイトのみのため間違った結果「1」を返す
  • 「kcountc( "\あ", "表" )」→ 第1引数にマルチバイトを含むため正しい結果「0」を返す。



0 件のコメント:

コメントを投稿