全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
5709 10
2012-11-07
data ex;
input x;
cards;
1
2
3
;
run;

%macro prob(prob=,newdata=);
data temp;  /*这里举个简单的例子,让ex表中x乘以prob,并放入到temp表中*/
set ex;
x=x*&prob;
run;
%if %sysfunc(exist(&newdata)) eq 0 %then %do;/*这里判断新表是否存在,如果不存在,新建新表,set上述temp表*/
data &newdata;
set temp;
run;
%end;
%else %do;   /*如果新表存在,将新表与temp纵向连接,并覆盖新表*/
data &newdata;
set &newdata temp;
run;
%end;
%mend;
/*以如下方式实现,初始阶段,没有out这张表*/
%prob(prob=1,newdata=out);/*out表不存在,data out;set temp;run;*/
%prob(prob=10,newdata=out);/*此时out表已存在,data out;set out temp;run*/
%prob(prob=100,newdata=out);/*此时out表已存在,data out;set out temp;run*/
/*最终out表中有9个观测,分别为
1
2
3
10
20
30
100
200
300*/
/*若将1,10,100三个乘数放在ex1表中,以call execute实现上述过程*/
data ex1;
input y;
cards;
1   
10  
100
;
run;
options mprint;
data _null_;
set ex1;
call execute('%prob(prob='||y||',newdata=out)');
run;
/*最终out表中数据仅有三行
100
200
300*/
/*解析出的代码如下
data temp;x=x*1;run;
data out;set temp; run;

data temp;x=x*10;run;
data out;set temp; run;

data temp;x=x*100;run;
data out;set temp; run;
即第一步解析出out表不存在,生成out表;
然而在第二步时,并不去判断out表是否存在,仍然用第一步解析出的代码,
第三步同样*/
我猜想call execute 在调用宏时,只在一开始对宏解析一次,接下来便不再解析。
不知道这样的猜想对不对,希望清楚的朋友,能够指点一下,十分感谢!

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2012-11-7 23:09:04
我的理解是:
如果data step包含call execute,比如你程序中的data _null_,SAS先生成code,在这个data _null_结束后,再开始编译和执行。这点你可以从mprint看出来。
然而在生成code的时候,macro instructions会同时执行,比如这句%if %sysfunc(exist(&newdata)) eq 0 %then %do,因为data out在生成code的时候是不存在的,所以生成的永远是%else 的那段code。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2012-11-8 16:59:11
yuerqieqie 发表于 2012-11-7 23:09
我的理解是:
如果data step包含call execute,比如你程序中的data _null_,SAS先生成code,在这个data _n ...
call execute 是实现数据步与宏之间的交互的;
如果解析到call execute中的宏没有调用的话,那会等到数据步结束之后才执行这个宏;
可是这边有调用数据步的y,肯定是交互式进行的;
只是以前没想到过宏中如果有%if  %do 这类函数到底怎么解析。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2012-11-8 20:08:07
ziyenano 发表于 2012-11-8 16:59
call execute 是实现数据步与宏之间的交互的;
如果解析到call execute中的宏没有调用的话,那会等到数据 ...
应该是这样的:
call execute() 中的代码涉及到宏的调用时,宏的执行时间有三种可能。即
1. 在DATA步编译时, 如 call execute("%test");
2. 在DATA步执行时,如 call execute( ‘%test’ );
3. 在DATA步执行后,如 call execute( '%'||"test');

这个例子应该属于第二种,即宏执行于DATA步执行过程中,而宏产生的SAS代码会在DATA步结束后才执行。所以宏运行时数据集&newdata不可能存在。

这样应该就可以达到想要的效果了:
data _null_;
set ex1;
if _n_=1 then  call execute('%prob(prob='||y||',newdata=out)');
else call execute('%'||'prob(prob='||y||',newdata=out)');

run;
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2012-11-8 20:51:15
pobel 发表于 2012-11-8 20:08
应该是这样的:
call execute() 中的代码涉及到宏的调用时,宏的执行时间有三种可能。即
1. 在DATA步编 ...
感谢pobel,如此细致的回答!同时也感谢楼上那位兄弟~
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2012-11-8 22:26:52
我run了你提到的三种方法,从log上看第二种的确和另外两种有区别,感觉是在和data step交互的同时在编译执行call execute里的东西,但结果都是一样的,说明不论用什么方法&newdata始终不存在。
我也尝试了您提到的
复制代码

并没有得到我想要的结果。是我什么地方理解错了么?请指点。谢谢

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群