标题: 大家能不能帮看看宏程序问题出在哪里? [打印本页] 作者: shiyiming 时间: 2008-4-10 13:19 标题: 大家能不能帮看看宏程序问题出在哪里? 代码如下,但是好像sh180parame文件中的eventzqdm ,eventdate没有被传到
宏程序calcu中来,不知问题在哪里?
%macro calcu(eventzqdm,eventdate);
data test1;
set test;
if zqdm ^=&eventzqdm&i then delete; /*判断eventzqdm并删除无关数据*/
obs=_n_;
run;
proc sql noprint;
select obs into:num from test1
where tradedate=&eventdate&i; /*判断eventdate*/
quit;
data betafirm;
set test1;
where %eval(&num-10)<=obs<=%eval(&num+10);
run;
data index1;
set index;
obs=_n_;
run;
proc sql noprint;
select obs into:num from index1
where tradedate=&eventdate&i;
quit;
data beta_mkt;
set index1;
where %eval(&num-10)<=obs<=%eval(&num+10);
run;
data betaboth;
merge betafirm beta_mkt;
run;
proc reg noprint data=betaboth outest=Coefout;
model ret=indexret;
quit;
data _null_;
set coefout;
call symput('nextalpha',intercept);
call symput('nextbeta',indexret);
run;
data eventfirm;
set test1;
where %eval(&num-30)<=obs<=%eval(&num-11);
run;
data event_mkt;
set index1;
where %eval(&num-30)<=obs<=%eval(&num-11);
run;
data Car_calc;
merge eventfirm event_mkt;
by tradedate;
if _N_=1 then Car=ret-(&nextalpha + &nextbeta*indexret);
else car =ret-(&nextalpha + &nextbeta*indexret)+holdcar;
holdcar=car;
retain holdcar;
alpha=&nextalpha;
beta=&nextbeta;
run;
%macro main;
%global num nextalpha nextbeta betanobs;
data _null_;
set sh180parame end=last;
call symput (('eventzqdm'||compress(_n_)),zqdm);
call symput(('eventdate'||compress(_n_)),ltdate);
if last then call symput('num',_n_);
run;
%do i=1 %to &num;
%calcu(&&eventzqdm&i,&&eventdate&i);
%end;
%mend main;
%main;
数据附件发不了:(,参见
<!-- m --><a class="postlink" href="http://sasor.feoh.net/modules.php?name=Forums&file=viewtopic&t=3814&sid=75aeded195dc90a965a9e5aec9e2d62a">http://sasor.feoh.net/modules.php?name= ... aec9e2d62a</a><!-- m -->作者: shiyiming 时间: 2008-4-10 17:47 标题: Re: 大家能不能帮看看宏程序问题出在哪里? 初步看了并且运行了一下,没有问题啊,eventzqdm和eventdate能够被顺利的传递。一部分log如下:
[quote:1ao9n0sn]MLOGIC(MAIN): %DO loop beginning; index variable I; start value is 1; stop value is 2; by value
is 1.
MLOGIC(CALCU): Beginning execution.
MLOGIC(CALCU): Parameter EVENTZQDM has value 600000
MLOGIC(CALCU): Parameter EVENTDATE has value 20070514
MPRINT(CALCU): data test1;
MPRINT(CALCU): set test;
ERROR: File WORK.TEST.DATA does not exist.
MPRINT(CALCU): if zqdm ^=6000001 then delete;
MPRINT(CALCU): obs=_n_;
MPRINT(CALCU): run;
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.TEST1 may be incomplete. When this step was stopped there were 0
observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MPRINT(CALCU): proc sql noprint;
MPRINT(CALCU): select obs into:num from test1 where tradedate=200705141;
ERROR: The following columns were not found in the contributing tables: tradedate.
MPRINT(CALCU): quit;
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds[/quote:1ao9n0sn]
数据量小的话,就把数据程序贴上来嘛,像这样:
[code:1ao9n0sn]data sh180parame;
infile datalines;
input zqdm $ ltdate $;
datalines;
600000 20070514
600001 20070430
;
run;[/code:1ao9n0sn]
还缺test数据。
我可以帮你debug一下。看一眼已经发现不少问题:
1、%macro calcu(eventzqdm,eventdate);/
最后干嘛加个“/”?
2、proc append base= Cars data=Car_calc(drop=holdcar);
怎么没有“run;”啊?
你得尽量把干净的程序放上来,还有这样的错误真实不应该啊。
如果有可能程序再缩短些,这样大家就会愿意帮你debug了。如果需要别人更好的帮助,最好把你的log也贴上来,log对于我们定位问题才是更有用的。
还有个建议,这样的lookup技术推荐使用hash object来做,执行又快,程序又简单。本论坛有不少例子的。作者: shiyiming 时间: 2008-4-10 20:24 标题: Re: 大家能不能帮看看宏程序问题出在哪里? 是传递错误吧。
[quote:1volt2ap]
%macro calcu(eventzqdm,eventdate);/
data test1;
set test;
if zqdm ^=&eventzqdm&i then delete; /*判断eventzqdm并删除无关数据*/
obs=_n_;
run;
[/quote:1volt2ap]
看[quote:1volt2ap]&eventzqdm&i [/quote:1volt2ap]在第一循环中&eventzqdm solve 为600000,同时&i solve 为1,连起来不就是6000001吗。显然在test中没有这样的值啊。
NOTE: Copyright (c) 2002-2003 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) 9.1 (TS1M3 DBCS3054)
Licensed to DANKOOK UNIVERSITY, Site 0038249001.
NOTE: 该会话正在执行,平台: XP_PRO
NOTE: SAS 9.1.3 SP4 (E9BX01)
NOTE: SAS 初始化所用时间:
实际时间 4.46 秒
CPU 时间 0.65 秒
NOTE: 从数据集 _EXP0_.INDEX 读取了 534 个观测。
NOTE: 数据集 WORK.INDEX 有 534 个观测和 2 个变量。
NOTE: 从数据集 _EXP0_.SH180PARAME 读取了 2 个观测。
NOTE: 数据集 WORK.SH180PARAME 有 2 个观测和 2 个变量。
NOTE: 从数据集 _EXP0_.TEST 读取了 1068 个观测。
NOTE: 数据集 WORK.TEST 有 1068 个观测和 3 个变量。
1
2
3 %macro calcu(eventzqdm,eventdate);/*isolate subset of data for a given company, calc Beta on
3 ! releveant range;
4 calc CAR on event window; append event period data to Results dataset*/
5
6 data test1;
7 set test;
8 if zqdm ^=&eventzqdm&i then delete; /*判断eventzqdm并删除无关数据*/
9 obs=_n_;
10 run;
11
12
13 proc sql noprint;
14 select obs into:num from test1
15 where tradedate=&eventdate&i; /*判断eventdate*/
16 quit;
17
18 data betafirm;
19 set test1;
20 where %eval(&num-10)<=obs<=%eval(&num+10);
21 run;
22
23 data index1;
24 set index;
25 obs=_n_;
26 run;
27
28
29 proc sql noprint;
30 select obs into:num from index1
31 where tradedate=&eventdate;
32 quit;
33
34 data beta_mkt;
35 set index1;
36 where %eval(&num-10)<=obs<=%eval(&num+10);
37 run;
38
39 data betaboth;
40 merge betafirm beta_mkt;
41 run;
42
43 proc reg noprint data=betaboth outest=Coefout;
44 model ret=indexret;
45 quit;
46
47 data _null_;
48 set coefout;
49 call symput('nextalpha',intercept);
50 call symput('nextbeta',indexret);
51 run;
52
53
54 data eventfirm;
55 set test1;
56 where %eval(&num-30)<=obs<=%eval(&num-11);
57 run;
58
59 data event_mkt;
60 set index1;
61 where %eval(&num-30)<=obs<=%eval(&num-11);
62 run;
63
64 data Car_calc;
65 merge eventfirm event_mkt;
66 by tradedate;
67 if _N_=1 then Car=ret-(&nextalpha + &nextbeta*indexret);
68 else car =ret-(&nextalpha + &nextbeta*indexret)+holdcar;
69 holdcar=car;
70 retain holdcar;
71 alpha=&nextalpha;
72 beta=&nextbeta;
73 run;
74
75 proc append base= Cars data=Car_calc(drop=holdcar);
76
77 %mend calcu;
78
79
80 %macro main;
81 %global num nextalpha nextbeta betanobs;
82 data _null_;
83 set sh180parame end=last;
84 call symput (('eventzqdm'||compress(_n_)),zqdm);
85 call symput(('eventdate'||compress(_n_)),ltdate);
86 if last then call symput('num',_n_);
87 run;
88 %do i=1 %to &num;
89 %calcu(&&eventzqdm&i,&&eventdate&i);
90 %end;
91 %mend main;
92
93 %main;
ERROR: No valid observations are found.
NOTE: The data set WORK.COEFOUT has 0 observations and 7 variables.
NOTE: PROCEDURE REG used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds[/quote:1zkimpxc]
程序中只有错误
[code:1zkimpxc]where tradedate="&&eventdate&i";[/code:1zkimpxc]
[code:1zkimpxc]where tradedate="&eventdate"; [/code:1zkimpxc]
宏传递肯定没有错误,可能是数据错误
hash object参考可在论坛里自己搜索,只列一个经典的
<!-- l --><a class="postlink-local" href="http://www.mysas.net/forum/viewtopic.php?f=4&t=3573#p11606">viewtopic.php?f=4&t=3573#p11606</a><!-- l -->作者: shiyiming 时间: 2008-4-11 18:26 标题: Re: 大家能不能帮看看宏程序问题出在哪里? 首先声明:本人lili83xu与edle素不相识,只是出于对sas感兴趣,就看了下edle的问题,顺着底下的超链接,把test数据贴出来。
对于edle的问题,看了下,疑惑有三:
1. 在macro main中调用了macro calcu,如下
[quote:eai2i0c4]%calcu(&&eventzqdm&i,&&eventdate&i) [/quote:eai2i0c4]回到calcu,可见[quote:eai2i0c4]%macro calcu(eventzqdm,eventdate)[/quote:eai2i0c4]即在第一次循环中把(600000,20070514)传递给(&eventzqdm,&eventdate)。而在%macro calcu()下面[quote:eai2i0c4]if zqdm ^=&eventzqdm&i then delete; /*判断eventzqdm并删除无关数据*/
[/quote:eai2i0c4],这里&eventzqdm&i显然被理解为6000001。注意到test中zqdm的值为600000与600001,因此在sas log中就出现了[quote:eai2i0c4]NOTE: 数据集 WORK.TEST1 有 0 个观测和 4 个变量[/quote:eai2i0c4]。
2. 对于[quote:eai2i0c4]
13 proc sql noprint;
14 select obs into:num from test1
15 where tradedate=&eventdate&i; /*判断eventdate*/
16 quit;
[/quote:eai2i0c4]
为什么sas log中会出现
[quote:eai2i0c4]ERROR: 用 等于 (=) 的表达式具有不同数据类型的组件。
NOTE: SAS 系统由于错误而停止了该步的处理。
[/quote:eai2i0c4]
但如果将其改为where tradedate='20070514';就对了。这个问题想请教高手。:)
3. [quote:eai2i0c4]
54 data eventfirm;
55 set test1;
56 where %eval(&num-30)<=obs<=%eval(&num-11);
57 run;
58
59 data event_mkt;
60 set index1;
61 where %eval(&num-30)<=obs<=%eval(&num-11);
62 run;
[/quote:eai2i0c4]
这两处的&num真的是同一个吗?如果是的话,在第二次循环中eventfirm的observations为0。
下面将code改了下,不知是否合你意?(假设所用数据已保存在work里)
[code:eai2i0c4]
%macro calcu(eventzqdm,eventdate);
data test1;
set test;
if zqdm=&eventzqdm;
obs=_n_;
run;
data test2;
set test1;
if tradedate=&eventdate;
run;
proc sql noprint;
select obs into :num1
from test2
;
quit;
data betafirm;
set test1;
where %eval(&num1-10)<=obs<=%eval(&num1+10);
run;
data index1;
set index;
obs=_n_;
run;
data index2;
set index1;
if tradedate=&eventdate;
run;
proc sql noprint;
select obs into:num2
from index2
quit;
data beta_mkt;
set index1;
where %eval(&num2-10)<=obs<=%eval(&num2+10);
run;
data betaboth;
merge betafirm beta_mkt;
run;
proc reg noprint data=betaboth outest=Coefout;
model ret=indexret;
quit;
data _null_;
set coefout;
call symput('nextalpha',intercept);
call symput('nextbeta',indexret);
run;
data eventfirm;
set test1;
where %eval(&num1-30)<=obs<=%eval(&num1-11);
run;
data event_mkt;
set index1;
where %eval(&num2-30)<=obs<=%eval(&num2-11);
run;
data Car_calc;
merge eventfirm event_mkt;
by tradedate;
if _N_=1 then Car=ret-(&nextalpha + &nextbeta*indexret);
else car =ret-(&nextalpha + &nextbeta*indexret)+holdcar;
holdcar=car;
retain holdcar;
alpha=&nextalpha;
beta=&nextbeta;
run;
%macro main;
%global num nextalpha nextbeta betanobs;
data _null_;
set sh180parame end=last;
call symput (('eventzqdm'||compress(_n_)),zqdm);
call symput(('eventdate'||compress(_n_)),ltdate);
if last then call symput('num',_n_);
run;
%do i=1 %to &num;
%calcu(&&eventzqdm&i,&&eventdate&i);
%end;
%mend main;
%main;
[/code:eai2i0c4]作者: shiyiming 时间: 2008-4-11 22:59 标题: Re: 大家能不能帮看看宏程序问题出在哪里? 用where语句不能传递&eventzqdm and &eventdate,用if 语句却可以,如在lili的程序中
[code:200jmyr4]data test2;
set test1;
if tradedate=&eventdate;
run;
proc sql noprint ;
select obs into :num1
from test2;
quit; [/code:200jmyr4]
运行起来可以传递,
而我最先的程序中
[code:200jmyr4]proc sql noprint ;
select obs into :num1 from test1
where tradedate=&eventdate; /*判断eventdate*/
quit;[/code:200jmyr4]
却无法运行。
找了一下原因,原来是没有加"",如将上面语句改一下即可
[code:200jmyr4]proc sql noprint ;
select obs into :num1 from test1
where tradedate="&eventdate"; /*判断eventdate*/
quit;[/code:200jmyr4]
把lili给出的macro calcu语句用where语句简化如下
[code:200jmyr4]%macro calcu(eventzqdm,eventdate);
data test1;
set test;
if zqdm=&eventzqdm;
obs=_n_;
run;
proc sql noprint ;
select obs into :num1 from test1
where tradedate="&eventdate"; /*判断eventdate*/
quit;
data betafirm;
set test1;
where %eval(&num1-10)<=obs<=%eval(&num1+10);
run;
data index1;
set index;
obs=_n_;
run;
proc sql noprint ;
select obs into: num2 from index1
where tradedate="&eventdate"; /*判断eventdate*/
quit;
data beta_mkt;
set index1;
where %eval(&num2-10)<=obs<=%eval(&num2+10);
run;
data betaboth;
merge betafirm beta_mkt;
by tradedate;
drop obs;
run;
proc reg noprint data=betaboth outest=Coefout;
model ret=indexret;
run;
data _null_;
set coefout;
call symput('nextalpha',intercept);
call symput('nextbeta',indexret);
run;
data eventfirm;
set test1;
where %eval(&num1-30)<=obs<=%eval(&num1-11);
run;
data event_mkt;
set index1;
where %eval(&num2-30)<=obs<=%eval(&num2-11);
run;
data Car_calc;
merge eventfirm event_mkt;
by tradedate;
drop obs;
if _N_=1 then Car=ret-(&nextalpha + &nextbeta*indexret);
else car =ret-(&nextalpha + &nextbeta*indexret)+holdcar;
holdcar=car;
retain holdcar;
alpha=&nextalpha;
beta=&nextbeta;
run;