SAS矩阵重组

2020-07-17 11:31:06 浏览数 (1)

最近看到一个群友提的一个问题:将上图中的名为HAVE的数据集转置成名为WANT的数据集。实现的方法有多种,最易懂的方法应该是TRANSPOSE,下面介绍其他几种方法:

  • FILENAME:
代码语言:txt复制
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:
代码语言:txt复制
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会简单点,因为不用去算行或列数。

0 人点赞