最近看到一个群友提的一个问题:将上图中的名为HAVE的数据集转置成名为WANT的数据集。实现的方法有多种,最易懂的方法应该是TRANSPOSE,下面介绍其他几种方法:
- FILENAME:
data have;
a_t1=1; b_t1=2; a_t2=3; b_t2=4; a_t3=5; b_t3=6; a_t4=7; b_t4=8;
run;
filename code temp;
data _null_;
file code;
set have;
array vlst{*} _numeric_;
do i=1 to dim(vlst) BY 2;
N1=vname(vlst{i});
N2=vname(vlst{i 1});
N3=prxchange('s/(w ?)_(w )/1_2=1/', -1, catx(' ', N1, N2));
N4=scan(N1, 2, '_');
put ' SET have(keep=' N1 N2' rename=(' N3 '));' @@;
put ' NAME="' N4 '";
output;';
end;
run;
data want;
length NAME $32;
%inc code;
run;
- CALL EXECUTE:
data temp;
set have;
array vlst{*} _numeric_;
do i=1 to dim(vlst) BY 2;
N1=vname(vlst{i});
N2=vname(vlst{i 1});
N3=prxchange('s/(w ?)_(w )/1_2=1/', -1, catx(' ', N1, N2));
N4=scan(N1, 2, '_');
keep N:;
output;
end;
run;
data want;
set temp end=last;
if _n_=1 then call execute('data want; length NAME $32;');
call execute('SET have(keep='||catx(' ', N1, N2)||' rename=('||cats(N3)||')); NAME="' ||cats(N4)||'"; output;');
if last then call execute('run;');
run;
可能大家会觉得上面两种方法代码行数都有点多,那请看下面采用SAS/IML的方法:
代码语言:txt复制proc iml;
use have;
read all var _NUM_ into M1[c=VARNAMES];
close;
NAME1=scan(VARNAMES, 1, '_');
NAME2=scan(VARNAMES, -1, '_');
ROW=unique(NAME1);
NAME=unique(NAME2);
M2=shape(M1, 0, 2);
create want from M2[c=ROW r=NAME];
append from M2[r=NAME];
close;
quit;
注意,上面函数SHAPE中的行数我写成0,这样真正的行数就由列数决定,即重组1行8列的矩阵,转成2列的情况下,行数只能是4了。故在行列很多的情况下把行或列数设为0会简单点,因为不用去算行或列数。