matrix - 计算基础 sas 中的矩阵乘积(不使用 IML)

标签 matrix sas

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

  1. 首先,我将矩阵设置为长格式(列、行、值)
  2. 我使用 proc sql 计算 2 个矩阵的乘积。
  3. 我使用 proc transpose 将前面步骤的结果放入宽格式中。

我的问题是有更简单的方法吗?或者至少如何简化我的代码?

这是我的代码:

/* 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。使用 reshape 和 SQL 连接的方法大约需要 1.5 秒,而使用合并的方法大约需要 0.2 秒。

关于matrix - 计算基础 sas 中的矩阵乘积(不使用 IML),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22001902/

相关文章:

python - 如何创建频率矩阵?

sas - 如何删除特殊 ASCII 字符?

sql-server - WHERE 子句运算符需要兼容的变量

sas - 我可以更改 SAS 中 CALL EXECUTE 堆栈的执行顺序吗?

sas - 在 SAS (Windows) 中获取随机文件的文件大小

math - 如何计算 2^n 模 1000000007 , n = 10^9

python - 如何在 Pytorch 中创建上三角矩阵?

python - numpy.dot(a, b) 在具有相似维度的矩阵相乘时给出错误的结果

matlab - 具有/不同列数的 vec2mat

SAS ODS : Multiple tables from a PROC TABULATE to a PNG