Sas Proc sql和宏变量
我正在尝试运行一个代码,该代码应该在考虑不同因素的情况下创建的表上运行。由于这些因素可能超过1,我决定创建一个宏%let来列出它们:Sas Proc sql和宏变量,sas,Sas,我正在尝试运行一个代码,该代码应该在考虑不同因素的情况下创建的表上运行。由于这些因素可能超过1,我决定创建一个宏%let来列出它们: %let list= factor1 factor2 ...; 我想做的是运行一段代码,使用不同的因子创建这些表。对于每个因子,我使用proc平均值和标准偏差计算,因此我应该在proc平均值为每个因子创建的表中有变量&list.\u mean and&list.\u stddev。这个表被标记为t2,我需要连接到另一个表t1。从t1开始,我考虑所有变量 因此,我
%let list= factor1 factor2 ...;
我想做的是运行一段代码,使用不同的因子创建这些表。对于每个因子,我使用proc平均值和标准偏差计算,因此我应该在proc平均值为每个因子创建的表中有变量&list.\u mean and&list.\u stddev。这个表被标记为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;
另一个是第二因子。
更新代码:
%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;
我的问题是如何考虑多个因素,定义为宏作为一个列表,作为表的列和作为宏的输入数据,例如:%TestDATABETE,TabLeNAMEY,List. 我怀疑试图使用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测试它,使用性别作为时间变量,身高和体重作为分析变量
%test_v1(_dtb=sashelp,_input=class,_output=want,_time=sex,_factor=height weight);
我怀疑试图使用procsql是使问题变得困难的原因。如果您坚持只使用普通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测试它,使用性别作为时间变量,身高和体重作为分析变量
%test_v1(_dtb=sashelp,_input=class,_output=want,_time=sex,_factor=height weight);
您可以尝试通过扫描因子列表将宏循环添加到宏中。它可能看起来像:
%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 |
+------+---------+---------+
新数据系数1:
+------+---------+---------+---------+--------------+
| 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 |
+------+---------+---------+---------+--------------+
新数据系数2:
+------+---------+---------+----------+--------------+
| 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 |
+------+---------+---------+----------+--------------+
您可以尝试通过扫描因子列表将宏循环添加到宏中。它可能看起来像:
%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 |
+------+---------+---------+
新数据系数1:
+------+---------+---------+---------+--------------+
| 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 |
+------+---------+---------+---------+--------------+
新数据系数2:
+------+---------+---------+----------+--------------+
| 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 |
+------+---------+---------+----------+--------------+
即使您修复了语法错误,您的计划也无法运行。您不能将FACTOR1和FACTOR2都重命名为同一个名称。我认为您可以使用一步过程排序,而不是两步数据+过程排序:过程排序数据=have1keep=time FACTOR1 out=have3\u 1;按系数1计算;跑代替数据2;设置have1;保持时间系数1;跑proc sort data=have2 out=have2_1;按系数1计算;跑为什么宏引用一个完全未定义的宏变量,col\u period?为什么按因子变量而不是按时间排序?您是否将因子变量用作分析变量或分组变量?即使您修复了语法错误,您的计划也无法运行。您不能将FACTOR1和FACTOR2都重命名为同一个名称。我认为您可以使用一步过程排序,而不是两步数据+过程排序:过程排序数据=have1keep=time FACTOR1 out=have3\u 1;按系数1计算;跑代替数据2;设置have1;保持时间系数1;跑proc sort data=have2 out=have2_1;按系数1计算;跑为什么宏引用一个完全未定义的宏变量,col\u period?为什么按因子变量而不是按时间排序?您是否将因子变量用作分析变量或分组变量?错误22-322:语法错误,应为以下之一:!、!!、&、*、***、+、'、'、-、/、=、?,和,AS,CONTAINS,EQ,EQT,FROM,GE,GET,GT,GTT,LE,LET,LIKE,LT,LTT,NE,NET,OR,^=,|,| |,~=。这就是我得到的错误。procsql的问题是我是这样应用的。只有第一个因子,因子1,所以我有t2。因子1,因子2,这是错误的,我应该有:t2。因子1,t2。factor2@a.rimbaud正如Tom所示,Proc MEANS有一个大的功能集供您使用。与只将args替换为语句的宏编码不同,学习Procs语句和不使用宏编码意味着支持长期的代码更少,并且使编码器或代码继承器的工作更轻松。错误22-322:语法错误,应为以下之一:!、!!、&、*、**、+、'、'、-、/、=、?,和,AS,CONTAINS,EQ,EQT,FROM,GE,GET,GT,GTT,LE,LET,LIKE,LT,LTT,NE,NET,OR,^=,|,| |,~=。这就是我得到的错误。procsql的问题是我是这样应用的。只有第一个因子,因子1,所以我有t2。因子1,因子2,这是错误的,我应该有:t2。因子1,t2。factor2@a.rimbaud正如Tom所示,Proc MEANS有一个大的功能集供您使用。不是简单地将args替换为语句来编码宏,而是学习Procs语句,不使用宏来编码,这意味着支持长期性的代码更少,并且使编码者或代码继承者的生活更轻松。T
汉克斯·阿列克西让列表=系数1系数2;我是这样写的:%macro testlist;%i=1%到%sysfunccountw&列表,%str;%let factorname=%scan&list,&i,%str;%宏v1数据集、表、时间和列表;%结束%修复试验;但没有返回任何输出。我在宏_v1中也使用了list,对吗?试试这个:%macro testlist;%i=1%到%sysfunccountw&列表,%str;%let factorname=%scan&list,&i,%str;%宏v1dataset、表、时间和factorname;%结束;%修补试验;%测试列表;它给了我以下错误:错误:文本表达式&list包含对宏变量list的递归引用。宏变量将被分配空值。@a.rimbaud tfactor从factor_列表中存储一个因子,并在每次迭代中更改。例如,我们有factor_list等于factor1 factor2 factor3,countw函数计算按空格分割的单词数,然后按每个单词循环迭代,tfactor在每次迭代中包含单词在第一次迭代中tfactor包含factor_list的第一个单词,它等于factor1,等等。谢谢Alexey谢谢Alexey让列表=系数1系数2;我是这样写的:%macro testlist;%i=1%到%sysfunccountw&列表,%str;%let factorname=%scan&list,&i,%str;%宏v1数据集、表、时间和列表;%结束%修复试验;但没有返回任何输出。我在宏_v1中也使用了list,对吗?试试这个:%macro testlist;%i=1%到%sysfunccountw&列表,%str;%let factorname=%scan&list,&i,%str;%宏v1dataset、表、时间和factorname;%结束;%修补试验;%测试列表;它给了我以下错误:错误:文本表达式&list包含对宏变量list的递归引用。宏变量将被分配空值。@a.rimbaud tfactor从factor_列表中存储一个因子,并在每次迭代中更改。例如,我们有factor_list等于factor1 factor2 factor3,countw函数计算按空格分割的单词数,然后按每个单词循环迭代,tfactor在每次迭代中包含单词在第一次迭代中tfactor包含factor1的factor_list的第一个单词,等等。谢谢Alexey