ラベル compress の投稿を表示しています。 すべての投稿を表示
ラベル compress の投稿を表示しています。 すべての投稿を表示

目に見えない改行コードが邪魔をしてくる話

今、








こういう、どうってことないデータセットがあったとします。
Xは文字型です。

そして、

data A1;
 set Q1;
 Y=input(X,8.);
run;

というなんてことない処理(Xを数値化してYに割り当てる)を実行します。


結果は








え?

見た目は同じなのに2オブザベーション目だけ欠損値です。

ログにも、確かに欠損値が生成されたNoteはでていますが、






引数が無効と言われても、、。といった感じです。

これ、知らないと一生解決できないんじゃないか系のトラブルです。
以前紹介した「背筋が凍る、厄介でおっかない小数点誤差の話」
http://sas-tumesas.blogspot.jp/2014/03/blog-post_14.html
に似てますね。



実は冒頭のデータセットは

data Q1;
length X $10.;
 X='1';output;
 X=cats('0A'X,'1');output;
run;

というコードで生成したものです。

ん?2個目のXで、1にくっつけている'0A'Xってなに?

これ、実は改行コードの一部(ラインフィールド)を指定する意味をもった記述なんです。
通常、こいつと'0D'x(キャリッジリターン)を合わせて、改行をさせます。

こういう意味をもった記号があって(タブ('09'x)とか)、そいつらが往々にして
僕らの大切な時間と精神力を奪っていきます。

対策は簡単で

data A2;
 set Q1;
 Y=input(compress(X,'0A'X || '0D'X),8.);
run;

取り除いてからinputです。

例えば、エクセルからデータを読み込んでデータセットを作る場合なんかによくこの問題が
浮上します。

見栄えをよくするために、結構セル内改行つかったりしていることが多いんですよね。






COMPRESSの第3引数

恐らく、僕だけだと思うのですが、、

例えば、ある文字変数から数字だけを残して他の文字を消したい場合
= COMPRESS(変数,,'KD')
逆に文字だけ残したい場合、
= COMPRESS(変数,,'KF');

と書けます。
これはSASのFAQを見て覚えたんですが
http://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/ba250.html

その時、ちゃんと説明を読んでなかったのでしょう、KD、KFという固定された呪文というか、決まり文句だと思ってたんですが、違いました。
Kは残すという意味(多分keep) Dは数字という意味(多分digit)、それを組み合わせて、KDで「数字を残す」といったようにキーワードを組み合わせて、挙動を設定しているのでした。

数字を残すか、文字を残すと言った状況が多かったのでKDかKFばかり指定していたせいで気付くのが遅くなりました。

詳しくはヘルプや関数リファレンス等、正式なもので勉強していただけたらと思いますが
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212246.htm



簡単な例だけ

data Q1;
X='123 AaaaBb_';
run;





に対して

data A1;
set Q1;
A1=compress(X,'ab');/*aとbを取り除く*/
A2=compress(X,'ab','k'); /*aとbだけ残す*/
A3=compress(X,'ab','ik'); /*aとAとbとBだけ残すiは大文字小文字を無視する意味*/
A4=compress(X,,'d');/*数字を取り除く*/
A5=compress(X,,'kd');/*数字を残す*/
A6=compress(X,,'f');/*アンダースコアと文字を取り除く*/
A7=compress(X,,'kf');/*アンダースコアと文字を残す*/
A8=compress(X,,'l');/*アルファベット小文字を取り除く*/
run;

とすると


みたいな感じです。

多分、僕より詳しい方、山ほどいると思うので、もっと面白い使い方の例があれば教えてください。