楼主: ziyenano
5779 10

[问答] 有关 call execute的疑惑 [推广有奖]

  • 0关注
  • 52粉丝

院士

7%

还不是VIP/贵宾

-

威望
2
论坛币
6137 个
通用积分
27.3565
学术水平
338 点
热心指数
326 点
信用等级
298 点
经验
57352 点
帖子
879
精华
1
在线时间
4132 小时
注册时间
2012-1-4
最后登录
2025-5-7

楼主
ziyenano 发表于 2012-11-7 13:34:51 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
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 在调用宏时,只在一开始对宏解析一次,接下来便不再解析。
不知道这样的猜想对不对,希望清楚的朋友,能够指点一下,十分感谢!

二维码

扫码加我 拉你入群

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

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

关键词:EXECUTE Cute call cut ECU amp

回帖推荐

yuerqieqie 发表于2楼  查看完整内容

我的理解是: 如果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。

本帖被以下文库推荐

沙发
yuerqieqie 发表于 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。
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
ziyenano + 1 + 1 + 1 精彩帖子

总评分: 学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

藤椅
ziyenano 发表于 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 这类函数到底怎么解析。

板凳
pobel 在职认证  发表于 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;
已有 2 人评分学术水平 热心指数 信用等级 收起 理由
yuerqieqie + 1 + 1 + 1 精彩帖子
ziyenano + 1 + 1 + 1 精彩帖子

总评分: 学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

和谐拯救危机

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

地板
yuerqieqie 发表于 2012-11-8 22:26:52
我run了你提到的三种方法,从log上看第二种的确和另外两种有区别,感觉是在和data step交互的同时在编译执行call execute里的东西,但结果都是一样的,说明不论用什么方法&newdata始终不存在。
我也尝试了您提到的
  1. data _null_;
  2. set ex1;
  3. if _n_=1 then call execute('%prob(prob='||y||',newdata=out)');
  4. else call execute('%'||'prob(prob='||y||',newdata=out)');
  5. run;
复制代码

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

7
pobel 在职认证  发表于 2012-11-9 09:38:10
yuerqieqie 发表于 2012-11-8 22:26
我run了你提到的三种方法,从log上看第二种的确和另外两种有区别,感觉是在和data step交互的同时在编译执行 ...
您好!谢谢您提出的问题,上面“板凳”那一楼中的第3项应该是错的,也就是让宏在DATA步后再执行那一条。
“板凳”楼中的2,3条应该都是宏在DATA步运行的过程中执行,而生成的SAS代码将于DATA步执行完后再运行。

如果想让CALL execute()中宏的调用在DATA步后执行应该需要单引号和%NRSTR()同时应用才可以。

请看下面这个例子, 应该清楚一点:
  1. data ex;
  2. input x;
  3. cards;
  4. 1
  5. 2
  6. 3
  7. ;
  8. run;

  9. %macro prob(prob=,newdata=);
  10. data temp;
  11.         set ex;
  12.   x=x*&prob;
  13.   time=time( );
  14.   format time time.;
  15. run;

  16. data _null_;
  17.   call sleep(2,1);
  18. run;
  19. %if %sysfunc(exist(&newdata)) eq 0 %then %do;
  20.     %put ======================================;
  21.     %put ====From macro PROB: &newdata does not exist! %sysfunc(time(),time.);
  22.     %put ======================================;
  23.         data &newdata;
  24.                 set temp;
  25.         run;
  26. %end;
  27. %else %do;  
  28.     %put ======================================;
  29.     %put ====From macro PROB: &newdata already exists! %sysfunc(time(),time.);
  30.     %put ======================================;
  31.         data &newdata;
  32.                 set &newdata temp;
  33.         run;
  34. %end;
  35. %mend;

  36. data ex1;
  37. input y;
  38. cards;
  39.         1   
  40.         10  
  41.         100
  42. ;
  43. run;
  44. options mprint;

  45. data test;
  46.         set ex1 end=last;
  47.         time=time();
  48.         format time time.;

  49.         if _n_=1 then call execute('%prob(prob='||y||',newdata=out)');
  50.         else call execute('%nrstr(%prob(prob='||y||',newdata=out))');

  51.         if last then call sleep(3,1);
  52. run;
复制代码
已有 2 人评分学术水平 热心指数 信用等级 收起 理由
yuerqieqie + 1 + 1 + 1 精彩帖子
ziyenano + 1 + 1 + 1 精彩帖子

总评分: 学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

和谐拯救危机

8
pobel 在职认证  发表于 2012-11-9 09:40:13
ziyenano 发表于 2012-11-8 20:51
感谢pobel,如此细致的回答!同时也感谢楼上那位兄弟~
楼主,不好意思昨天的方法(“板凳”楼)是有问题的,如yuerqieqie在“地板”楼所说。

请看7楼的例子。
和谐拯救危机

9
ziyenano 发表于 2012-11-9 09:56:18
pobel 发表于 2012-11-9 09:40
楼主,不好意思昨天的方法(“板凳”楼)是有问题的,如yuerqieqie在“地板”楼所说。

请看7楼的例子。 ...
非常感谢pobel,昨天因为有事情,所以没去运行程序!这次没问题了,再次感谢您如此细致的回答~

10
yuerqieqie 发表于 2012-11-9 21:45:01
pobel 发表于 2012-11-9 09:38
您好!谢谢您提出的问题,上面“板凳”那一楼中的第3项应该是错的,也就是让宏在DATA步后再执行那一条。
...
非常感谢,学习到很多。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-9 13:36