以sas计算矩阵乘积(不使用IML)

时间:2014-02-25 00:07:17

标签: matrix sas

为了计算2个矩阵的乘积,我正在使用这个方法:

  1. 首先我把我的矩阵放在长格式(col,row,value)
  2. 我使用proc sql来计算2个矩阵的乘积。
  3. 我使用proc transpose将广告步骤的结果放在宽格式中。
  4. 我的问题是有更简单的方法吗?或者至少我如何简化我的代码?

    这里是我的代码:

    /* macro to put a matrix in the long format*/
    %macro reshape(in_A = , ou_A= );
        data &ou_A.;
        set &in_A.;
        array arr_A{*} _numeric_;
        row = _n_;
        do col = 1 to dim(arr_A);
            value = arr_A{col};
            output;
        end;
        keep row col value;
        run;
    %mend;
    
    
    
    %macro prod_mat( in_A = , in_B= ,ou_AB =);
      /* put the matrix in the long format */
        %reshape(in_A=&in_A.,ou_A=lA);
        %reshape(in_A=&in_B.,ou_A=lB);
      /* compute product */
        PROC SQL ;
        CREATE TABLE PAB AS
        SELECT lA.row, lB.col, SUM(lA.value * lB.value)  as value
            FROM lA JOIN lB ON lA.col = lB.row
         GROUP BY lA.row, lB.col;
        QUIT;
    
       /* reshape the output to the wide format */
        proc transpose data=PAB out=&ou_AB.(DROP=_name_) prefix=x;
            by row ;
            id col;
            var value;
        run;
    
    %mend;
    
    
    data A ; 
          input x1 x2 x3; 
        datalines ; 
        1 2 3
        3 4 4
        5 6 9
       ; 
    
    data B ; 
          input x1 x2; 
        datalines ; 
        1 2
        3 4 
        4 5
        ; 
    
    %prod_mat(in_A =A,in_B=B,ou_AB=AB)
    

1 个答案:

答案 0 :(得分:1)

嗯,这是我的变种。这不是代码本身比你的短,但对于大矩阵,它会更快地工作,因为它避免使用SQL-join与所有元素的笛卡尔积。 主要思想 - A的的完全连接(笛卡尔积)和转置的B,然后乘以相应的列。例如。如果是3x3和3x2矩阵,我们需要:

1)在合并数据集column1 * column4 + column2 * column5 + column3 * column6;

的每一行中相乘和求和

2)重复第二行;

3)输出一行中的两个值。

%macro prod_mat_merge(in_A =,in_B=,ou_AB=);
/*determine number of rows and columns in the 2nd matrix*/
%let B_id=%sysfunc(open(&in_B));
%let B_rows=%sysfunc(attrn(&B_id,nobs));
%let B_cols=%sysfunc(attrn(&B_id,nvars));
%let rc=%sysfunc(close(&B_id));

/*transpose the 2nd matrix*/
proc transpose data=&in_B out=t&in_B(drop=_:);run;

/*making Cartesian product of the 1st and transposed 2nd matrices*/
data &ou_AB;
    do until(eofA);
        set &in_A end=eofA;
        do i=1 to n;
            set t&in_B nobs=n point=i;
            output;
        end;
    end;
run;

/*multiplication*/
data &ou_AB;
    /*new columns for products, equal to number of columns in the 2nd matrix*/
    array p[&B_cols];
    do j=1 to &B_cols;
        p[j]=0;
        set &ou_AB;
        array col _ALL_;
        /*multiply corresponding pairs of columns*/
        do i=&B_cols+2 to &B_cols+1+&B_rows;
            p[j]+col[i]*col[i+&B_rows];
        end;
    end;
    output;
    keep p:;
run;
%mend prod_mat_merge;

我测试了两种方法,每种方法乘以两个随机矩阵100x100。重塑和SQL连接的方法需要大约1.5秒,而合并方法大约需要0.2秒。