複数回transposeしてからmergeする前にちょっと考えてみてって話

例えば以下のデータセットから

data Q1;
ID="001";VISITN=1;A=1;B=2;C=3;output;
ID="001";VISITN=2;A=3;B=4;C=5;output;
ID="002";VISITN=1;A=6;B=7;C=8;output;
ID="002";VISITN=2;A=9;B=0;C=1;output;
run;











以下の全転置データセットを作りたい場合










proc transpose data=Q1 out=_A prefix=A_;
  var A;
  id VISITN;
  by ID;
run;
proc transpose data=Q1 out=_B prefix=B_;
  var B;
  id VISITN;
  by ID;
run;
proc transpose data=Q1 out=_C prefix=C_;
  var C;
  id VISITN;
  by ID;
run;
data RES1;
merge _A _B _C;
by ID;
drop _NAME_;
run;

と書いたりします。

もちろん、これで正解です。
変数が10個なら10回transposeかければいいんですが、ちょっと工夫を考えてみます

例えば、今回の場合だと「ID」 と「パラメータ」と「値」で構成される縦積み構造にしてから転置すれば1回の転置でスムーズに結果がだせます。

つまり

data _Q1;
set Q1;
array ch A--C;
do over ch;
VNAME =vname(ch);
VAL=ch;
output;
end;
keep ID VNAME VISITN VAL;
run;
proc transpose data=_Q1 out=RES2(drop= _NAME_) delimiter=_;
  var VAL;
  id VNAME VISITN;
  by ID;
run;








というわけ(IDの複数指定ができるようになったのは9.3から)。

1回途中で作ってる縦積み構造(_Q1)の中身をみてみると




















となるわけです。


別にこっちの方法が正解だというわけではなく、状況に応じて考えましょうという話ですね。対象が文字列変数の場合、縦積み構造にするときに文字切れしないように最大lengthにしなければならないので注意が必要です。

SASの場合、BYやCLASSステートメントが強力なので、インプットやアウトプットの形にちょっと頭を使えば、同じ機能のステップを反復する必要がない状況が多いです。

まあ、言いたいことを一言で言うと、データステップも楽しい世界だよってことです。


4 件のコメント:

  1. 縦積み作業もtransposeでやれば、初めての方は混乱するかも・・・

    proc transpose data=Q1 out=_Q1(rename=Val1=Val) prefix=Val name=VName;
    by Id VisitN;
    var A B C;
    run;

    transposeを1回でなんとかならんかやってみたのですが無理でしたね。

    返信削除
  2. out=の部分が間違っていました。
    正しくは、out=_Q1(rename=(Val1=Val)) です。

    返信削除
  3. 有難うございます!2回transposeもありですね!
    忘備録で「TRANSPOSEの2回実行テクニック」http://sas-boubi.blogspot.jp/2015/06/transpose2.htmlとして、既に紹介されてました。うっかりしてました。

    返信削除
  4. 気分を害されるかと思ったのですが、さすがに度量が広いですね!
    2度漬けtransposeまで紹介していただけるとは感激です。
    transposeだけで片付けると結びの「データステップも楽しい世界」が失効しますし、私のコメントこそ邪魔なのです。

    返信削除