SAS IML在循环中使用Mattrib with Macro(symget)

时间:2015-01-08 10:14:53

标签: macros sas-iml string-to-symbol

在IML proc中,我有几个martices和几个带有列名称的向量:

proc IML;
    mydata1 = {1 2 3, 2 3 4};
    mydata2 = {1 2, 2 3};
    names1 = {'red'  'green' 'blue'};
    names2 = {'black' 'white'};

要将列名分配给矩阵中的列,可以足够地对mattrib语句进行复制:

    /*  mattrib mydata1 colname=names1;*/
    /*  mattrib mydata2 colname=names2;*/

但是,在我的情况下,矩阵的数量是在执行时定义的,因此需要一个do循环。以下代码

    varNumb=2;
    do idx=1 to varNumb;
        call symputx ('mydataX', cat('mydata',idx));
        call symputx ('namesX', cat('names',idx));
        mattrib (symget('mydataX')) colname=(symget('namesX'));
    end;

    print (mydata1[,'red']) (mydata2[,'white']);
quit;

然而产生"期待一个名字"第一个symget上的错误。

类似的问题Loop over names in SAS-IML?提供了symget的宏解决方法,这里会产生错误。

将mattrib与symget一起使用的正确方法是什么?是否有其他方法可以从字符串中创建变量而不是宏?

任何帮助都将不胜感激。

谢谢, 亚历


EDIT1

问题出在 symget 函数中。 & -sign解析宏变量中包含的矩阵的名称, symget 仅返回宏的名称。

proc IML;
    mydata1 = {1 2 3};
    call symputx ('mydataX', 'mydata1');
    mydataNew = (symget('mydataX'));

    print (&mydataX);
    print (symget("mydataX"));
    print mydataNew;
quit;

结果

mydata1 :   
1 2 3 

mydata1 

mydataNew :  
mydata1 

有什么想法吗?


EDIT2

函数解决了EDIT1中的 symget 问题

    mydataNew = value(symget('mydataX'));
    print (&mydataX);
    print (value(symget("mydataX")));
    print mydataNew;

mattrib 问题但仍然存在。


解决

谢谢Rick,你已经睁开眼睛看了CALL EXECUTE()语句。

1 个答案:

答案 0 :(得分:0)

使用CALL SYMPUTX时,不应对第二个参数使用引号。你的陈述

call symputx ('mydataX', 'mydata1');

将字符串'mydata1'分配给宏变量。

通常,尝试在SAS / IML循环中使用宏变量通常会导致代码复杂化。请参阅文章Macros and loops in the SAS/IML language,以了解尝试将宏预处理器与交互式语言相结合所导致的问题。因为MATTRIB语句需要矩阵名称的文字值,所以我建议您使用CALL EXECUTE而不是宏替换来执行MATTRIB语句。

您也遇到问题,因为宏变量始终是标量字符串,而列名称是字符串的向量。使用ROWCAT函数将名称向量连接成一个字符串。

以下陈述在不使用宏变量的情况下实现了您的目标:

/* Use CALL EXECUTE to set matrix attributes dynamically.
   Requires that matrixName and varNames be defined at main scope */
start SetMattrib;
   cmd =  "mattrib " + matrixName + " colname={" + varNames + "};";
   *print cmd;    /* for debugging */
   call execute(cmd);
finish;

varNumb=2;
do idx=1 to varNumb;
    matrixName = cat('mydata',idx);
    varNames = rowcat( value(cat('names',idx)) + " " );
    run SetMattrib;
end;