Matrix 在基本sas中计算矩阵积(不使用IML)

Matrix 在基本sas中计算矩阵积(不使用IML),matrix,sas,Matrix,Sas,为了计算两个矩阵的乘积,我使用以下方法: 首先,我将矩阵放在长格式中(列、行、值) 我使用procsql计算两个矩阵的乘积 我使用proc转置将前一步的结果转换为宽格式 我的问题是有更简单的方法吗?或者至少我如何简化我的代码 这是我的代码: /* macro to put a matrix in the long format*/ %macro reshape(in_A = , ou_A= ); data &ou_A.; set &in_A.; array

为了计算两个矩阵的乘积,我使用以下方法:

  • 首先,我将矩阵放在长格式中(列、行、值)
  • 我使用procsql计算两个矩阵的乘积
  • 我使用proc转置将前一步的结果转换为宽格式
  • 我的问题是有更简单的方法吗?或者至少我如何简化我的代码

    这是我的代码:

    /* 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)
    

    这是我的变体。并不是代码本身比您的短,而是对于大型矩阵,它的工作速度更快,因为它避免了使用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秒。

    谢谢!看起来很有希望!我是一个SAS新手(有时),我需要一些时间来消化这一点!您使用了许多内置函数%sysfunc、eofA、attrn等等,。。!再次感谢!