最近、迷った処理について
以下のようなデータがあったとします。
data Q1;
ID='001';TERM_1='頭痛';TERM_2='腹痛';TERM_3='頭痛';TERM_4='頭痛';output;
ID='002';TERM_1='下痢';TERM_2='腹痛';TERM_3='下痢';TERM_4='';output;
ID='003';TERM_1='腰痛';TERM_2='';TERM_3='';TERM_4='';output;
ID='004';TERM_1='';TERM_2='骨折';TERM_3='';TERM_4='骨折';output;
run;
ここから、
のようなデータセットを作れと言われたとします。
要は横方向に重複を除いてから連結しろってことで、
変数の数は可変、発生する重複の個数は可変で、どことどこが重複するかも
不明だとします
(必ず連続して2個重複とかなら、配列で要素番号-1を捉える条件式で対応できますね)
いいアイデアがなかったので、もう一端transposeで縦にデータ起こしてから、sortにnodupつけて
重複殺してから、再度、transposeして、と思ったのですが、それもちょっとイマイチだなと思って
以下の方法でやってみました。
data A1;
set Q1;
array AR{*} $ TERM_:;
do i=1 to dim(AR);
if AR{i}^='' and whichc(AR{i},of AR{*})<i then AR{i}='';
end;
ALLTERM=catx('、',of TERM_:);
run;
となって、IDとALLTERMだけkeepすれば、最初の作るべきデータセット同じになります。
青字の部分がミソで、要するに、自分の値で、自分自身を含む配列を検索して、最初に
見つかった位置番号が自分の要素番号より小さければ、自分の値は既に前の変数で
出現しているので、自分は要らない子なので消えようってことを順番に全変数分やって
生き残った値がユニークな値ってことです。
横方向に重複を取り除くのって、ぱっと思いつかないですね。
他に方法があれば教えてください。
配列は苦手なので、もっといい方法がある気がしてます。
call sortcルーチンにnodupオプションみたいなのがあれば一発解決な気がしますが、、。
追加されないかな
こんにちは!
返信削除私もこの場合transposeかけてnodupkeyしちゃいますねー。。
けどすごく面白い問題なので、何か面白い方法がないか考えてみました。
正規表現で多分うまく出来そうです↓
data A2;
length ALLTERM $200.;
set Q1;
call sortc(of TERM_:);
ALLTERM = catx(",", of TERM_:, "DAMMY");
ALLTERM = tranwrd( prxchange("s/(.+,)\1+/$1/",-1,ALLTERM) ,",DAMMY","");
run;
こんにちわ!!
返信削除もう、ほんとに、凄すぎですよ、、。いつもながら。
有難うございます!
そうか、正規表現をこういう風に使えるんですね。
まじで勉強しないと、、。
細切れにして、実行して、正規表現について検索しながら、10分ぐらい格闘して
ようやく何しているか理解しました。
でも実践でぱっとこれ書けるようになるまでには、だいぶ時間かかりそうです、、。
すみません。。最初に書いたプログラム、
返信削除たとえば「頭痛」が4件あった場合、最初のやつだとうまくいかないですね。。
正しくは、以下になります。
data A2;
length ALLTERM $200.;
set Q1;
call sortc(of TERM_:);
ALLTERM = catx(",", of TERM_:, "DAMMY");
ALLTERM = tranwrd( prxchange("s/(.+?,)\1+/$1/",-1,ALLTERM) ,",DAMMY","");
run;
私も正規表現が苦手なので、一発でうまく書けないことも多かったりします。
複雑な分、面白いし、マスターしたらかなり強力ですよね!