Proc SQL和宏变量

时间:2019-11-27 00:02:21

标签: sas

我正在尝试运行一个代码,该代码应该在考虑了不同因素而创建的表上工作。由于这些因素可能超过1,因此我决定创建一个宏%let来列出它们:

%let list= factor1 factor2 ...;

我想做的是运行代码来使用不同的因素创建这些表。对于每个因子,我使用proc means来计算平均值和标准偏差,因此在&list._mean为每个因子创建的表中应该有变量&list._stddevproc means 。该表被标记为t2,我需要加入另一个表t1。从t1开始,我正在考虑所有变量。

因此,我的主要困难在于proc sql:

proc sql;
create table new_table as
select t1.*
, t2.&list._mean as mean
, t2.&list._stddev as stddev
from table1 as t1
left join table2 as t2
on t1.time=t2.time
order by t2.&list.
quit;

此代码返回错误,我认为是因为我正在考虑t2.factor1 factor2,即t2仅适用于第一个因素,而不适用于第二个因素。 我期望的是以下内容:

  proc sql;
    create table new_table as
    select t1.*
    , t2.factor1._mean as mean
    , t2.factor1._stddev as stddev
    from table1 as t1
    left join table2 as t2
    on t1.time=t2.time
    order by t2.factor1.
    quit;

,另一个是因数2。 更新代码:

%macro test_v1(
     _dtb
    ,_input
    ,_output
    ,_time
    ,_factor
);

data &_input.;
    set &_dtb..&_input.;
    keep &_col_period. &_factor.;
run;

proc sort data = work.&_input.
           out = &_input._1;
    by &_factor. &_time.;
run;

%put ERROR: 2

proc means data=&_input._1 nonobs mean stddev;
    class &_time.;
    var &_factor.;
    output out=&_input._n (drop=_TYPE_) mean= stddev= /autoname ;
run;

%put ERROR: 3

proc sql;
create table work.&_input._data as 
select t1.*
        ,t2.&_factor._mean as mean
        ,t2.&_factor._stddev as stddev
from &_input. as t1
left join &_input._n as t2
on t1.&_time.=t2.&_time.
order by &_factor.;
quit;

%mend test_v1;

然后我的问题是如何考虑多个因素,这些因素在宏中定义为列表,表列以及宏中的输入数据(例如:%test(dataset, tablename, list)

2 个答案:

答案 0 :(得分:2)

我怀疑尝试使用PROC SQL会使问题更加棘手。如果您只使用普通的SAS语法,那么使用空格分隔的变量名列表将很容易使用。

因此,对您的代码进行一些调整:

%macro test_v1
(_dtb    /* Input libref */
,_input  /* Input member name */
,_output /* Output dataset */
,_time   /* Class/By variable(s) */
,_factor /* Analysis variable(s) */
);

proc sort data= &_dtb..&_input. out=_temp1;
  by &_time. ;
run;

proc means data=_temp1 nonobs mean stddev;
  by &_time.;
  var &_factor.;
  output out=_temp2 (drop=_TYPE_) mean= stddev= /autoname ;
run;

data &_output. ;
  merge _temp1 _temp2 ;
  by &_time.;
run;

%mend test_v1;

然后我们可以使用SASHELP.CLASS进行测试,方法是将SEX用作“时间”变量,并将HEIGHT和WEIGHT用作分析变量。

%test_v1(_dtb=sashelp,_input=class,_output=want,_time=sex,_factor=height weight);

enter image description here

答案 1 :(得分:2)

您可以尝试通过扫描因素列表来将宏循环添加到宏中。它可能看起来像:

%macro test(list);
   %do i=1 to %sysfunc(countw(&list,%str( )));
      %let factorname=%scan(&list,&i,%str( ));
       /* if macro variable list equals factor1 factor2 then there would be
       two iterations in loop, i=1 factorname=factor1 and i=2 factorname=2*/
      /*your code here*/
   %end
%mend test;

更新:

%macro test(_input, _output, factors_list); %macro d; %mend d;
%do i=1 %to %sysfunc(countw(&factors_list,%str( )));
%let tfactor=%scan(&factors_list,&i,%str( ));
proc sort data = work.&_input.
           out = &_input._1;
    by &factors_list. time;
run;

proc means data=&_input._1 nonobs mean stddev;
    class time;
    var &tfactor.;
    output out=&_input._num (drop=_TYPE_) mean= stddev= /autoname ;
run;

proc sql;
   create table &_output._&tfactor as
   select t1.*
   , t2.&tfactor._mean as mean
   , t2.&tfactor._stddev as stddev
   from &_input as t1
   left join &_input._num as t2
   on t1.time=t2.time
   order by t1.&tfactor;
quit;

%end;
%mend test;

%test(have,newdata,factor1 factor2);

有数据集:

+------+---------+---------+
| time | factor1 | factor2 |
+------+---------+---------+
|    1 |   12345 |    1234 |
|    2 |     123 |      12 |
|    3 |       1 |      -1 |
|    4 |     -12 |    -123 |
|    5 |   -1234 |  -12345 |
|    6 |    9876 |     987 |
|    7 |      98 |       8 |
|    8 |       9 |       7 |
|    1 |    1234 |     123 |
|    2 |      12 |       1 |
|    3 |      12 |     -12 |
|    4 |    -123 |   -1234 |
|    5 |  -12345 | -123456 |
|    6 |     987 |      98 |
|    7 |       9 |      -9 |
|    8 |    1234 |    1234 |
+------+---------+---------+

NEWDATA_FACTOR1:

+------+---------+---------+---------+--------------+
| time | factor1 | factor2 |  mean   |    stddev    |
+------+---------+---------+---------+--------------+
|    5 |  -12345 | -123456 | -6789.5 | 7856.6634458 |
|    5 |   -1234 |  -12345 | -6789.5 | 7856.6634458 |
|    4 |    -123 |   -1234 |   -67.5 | 78.488852712 |
|    4 |     -12 |    -123 |   -67.5 | 78.488852712 |
|    3 |       1 |      -1 |     6.5 | 7.7781745931 |
|    7 |       9 |      -9 |    53.5 | 62.932503526 |
|    8 |       9 |       7 |   621.5 | 866.20580695 |
|    3 |      12 |     -12 |     6.5 | 7.7781745931 |
|    2 |      12 |       1 |    67.5 | 78.488852712 |
|    7 |      98 |       8 |    53.5 | 62.932503526 |
|    2 |     123 |      12 |    67.5 | 78.488852712 |
|    6 |     987 |      98 |  5431.5 |  6285.472178 |
|    1 |    1234 |     123 |  6789.5 | 7856.6634458 |
|    8 |    1234 |    1234 |   621.5 | 866.20580695 |
|    6 |    9876 |     987 |  5431.5 |  6285.472178 |
|    1 |   12345 |    1234 |  6789.5 | 7856.6634458 |
+------+---------+---------+---------+--------------+

NEWDATA_FACTOR2:

+------+---------+---------+----------+--------------+
| time | factor1 | factor2 |   mean   |    stddev    |
+------+---------+---------+----------+--------------+
|    5 |  -12345 | -123456 | -67900.5 | 78567.341564 |
|    5 |   -1234 |  -12345 | -67900.5 | 78567.341564 |
|    4 |    -123 |   -1234 |   -678.5 |  785.5956339 |
|    4 |     -12 |    -123 |   -678.5 |  785.5956339 |
|    3 |      12 |     -12 |     -6.5 | 7.7781745931 |
|    7 |       9 |      -9 |     -0.5 |  12.02081528 |
|    3 |       1 |      -1 |     -6.5 | 7.7781745931 |
|    2 |      12 |       1 |      6.5 | 7.7781745931 |
|    8 |       9 |       7 |    620.5 | 867.62002052 |
|    7 |      98 |       8 |     -0.5 |  12.02081528 |
|    2 |     123 |      12 |      6.5 | 7.7781745931 |
|    6 |     987 |      98 |    542.5 | 628.61792847 |
|    1 |    1234 |     123 |    678.5 |  785.5956339 |
|    6 |    9876 |     987 |    542.5 | 628.61792847 |
|    1 |   12345 |    1234 |    678.5 |  785.5956339 |
|    8 |    1234 |    1234 |    620.5 | 867.62002052 |
+------+---------+---------+----------+--------------+