用于递增日期的sas宏

时间:2014-02-24 07:26:11

标签: macros sas

我的代码是:

libname " Cp/mydata"
options ;
%let yyyymmdd=20050210;
%let offset=0;
%let startrange=0;
%let endrange=0;

/* MACRO FOR INCREMENTING THE DATE */
%macro base(yyyymmdd=, offset=);
%local date x ds; /* declare macro variables with local scope */
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                   ,%substr(&yyyymmdd,7,2)
                   ,%substr(&yyyymmdd,1,4))); /* convert yyyymmdd to SAS date */
%let loopout=100;/* hardcoded - number of times to check whether ds exists */
%do x=&offset %to &loopout; /* begin loop */
   /* convert &date to yyyymmdd format */
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&offset),yymmddn8.); 
   %if %sysfunc(exist( &ds )) %then %do;
      %put &ds exists!;
      &ds /* write out the dataset, if it exists */
      %let x=&loopout; /* exit loop */
   %end;
   %else %do;
      %put &ds does not exist - checking subsequent day;
      %let date=&date+1;
   %end;
%end;
%mend;

%macro loop(yyyymmdd=, startrange=, endrange=);
%local date x ds;
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                      ,%substr(&yyyymmdd,7,2)
                      ,%substr(&yyyymmdd,1,4)));
data x;
set set %base(yyyymmdd=&yyyymmdd, offset=0)
/* loop through each specific dataset, checking first whether it exists.. */
%do x=&startrange %to &endrange;
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&x),yymmddn8.);
   %if %sysfunc(exist( &ds )) %then %do;
      &ds
   %end;
%end;
;
run;
%mend; 

这是我尝试运行此宏时生成的错误。

数据临时;

58 set%loop(yyyymmdd =& yyyymmdd,startrange =& startrange, 58! endrange =安培; endrange);

错误:文件WORK.DATA.DATA不存在。

错误:文件WORK.X.DATA不存在。

AQ.CO_20050210不存在 - 检查后续日

AQ.CO_20050211不存在 - 检查后续日

AQ.CO_20050212存在!

注意:由于错误,系统停止处理此步骤。

我想要两方面的帮助:

1)在这里,如果我的原始数据集中没有该日期,我正试图将日期增加1或2左右。请帮助使这个宏工作正常。

2)我想在我的数据中有另一列,即work.date,它将具有0或1(如果指定日期yyyymmdd存在于我们的原始数据中,则为1,如果我正在递增,则为0)。请在我的宏中进行指定的更改。 在此先感谢!!

2 个答案:

答案 0 :(得分:1)

我不太确定你的%base()宏正在尝试实现什么,但我注意到了一些事情。

首先尝试打开option mprint;以帮助调试。如果您仍需要更多调试信息,您也可以尝试打开以下选项(我建议您一次1个,直到您知道需要哪些选项):

option symbolgen macrogen mlogic;

其次,您的示例代码中只有set set而不是set。我不认为这有助于任何=)。

当我在我的机器上快速尝试代码时,我注意到当我调用%base()宏时,我遇到了一个奇怪的错误(与你的不同)。这似乎是一个不应该发生的错误所以我将调用包裹在%unquote()函数中以确保并且我开始收到您的帖子提到的错误。您可能也想尝试这个:

set %unquote(%base(yyyymmdd=&yyyymmdd, offset=0))

通常不需要%unquote()函数,除非您明确使用宏引用函数并获得奇怪的错误,但SAS宏有时似乎有自己的想法。当我知道这是必要的时候,我只会添加它。

此外,您的libname调用在行尾没有分号。

最后,关于使用SAS宏语言中的日期的一些建议。不要在日期值和格式化值之间进行转换。它会使您的代码更大,更容易出错并且更难以阅读。我知道,因为我过去常常这样做。请尝试始终使用包含实际日期值的变量(通过使用%sysfunc(mdy())的结果),然后如果需要格式化值,则创建一个新变量(例如%let yyyymmdd = %sysfunc(putn(&mydate),yymmddn8.);。当您通过时从一个宏到另一个宏的值,即使看起来更容易也不会传递格式化值,传递实际值。

进行上述更改会删除计算机上的所有错误。最终代码:

libname " Cp/mydata";

%let yyyymmdd=20050210;
%let offset=0;
%let startrange=0;
%let endrange=0;

/* MACRO FOR INCREMENTING THE DATE */
%macro base(yyyymmdd=, offset=);
%local date x ds; /* declare macro variables with local scope */
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                   ,%substr(&yyyymmdd,7,2)
                   ,%substr(&yyyymmdd,1,4))); /* convert yyyymmdd to SAS date */
%let loopout=100;/* hardcoded - number of times to check whether ds exists */
%do x=&offset %to &loopout; /* begin loop */
   /* convert &date to yyyymmdd format */
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&offset),yymmddn8.); 
   %if %sysfunc(exist( &ds )) %then %do;
      %put &ds exists!;
      &ds /* write out the dataset, if it exists */
      %let x=&loopout; /* exit loop */
   %end;
   %else %do;
      %put &ds does not exist - checking subsequent day;
      %let date=&date+1;
   %end;
%end;
%mend;

%macro loop(yyyymmdd=, startrange=, endrange=);
%local date x ds;
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                      ,%substr(&yyyymmdd,7,2)
                      ,%substr(&yyyymmdd,1,4)));
data x;
set %unquote( %base(yyyymmdd=&yyyymmdd, offset=0))
/* loop through each specific dataset, checking first whether it exists.. */
%do x=&startrange %to &endrange;
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&x),yymmddn8.);
   %if %sysfunc(exist( &ds )) %then %do;
      &ds
   %end;
%end;
;
run;
%mend; 
%loop(yyyymmdd=&yyyymmdd, startrange=&startrange, endrange=&endrange);

答案 1 :(得分:0)

在我看来,您的解决方案非常复杂。 但我相信至少有一个问题是我们的第二个宏(%循环)中的变量x:我看不到你在哪里定义它。

如果您不需要限制循环,您可以更轻松地完成所有这些操作。如果您只想要偏移量以外的所有数据集,可以通过使用SASHELP库来查找所需的数据集来简化所有这些操作。然后只是循环结果。

弃用回复,误读了需要 你正在重新发明轮子,深入研究intnx和intck函数。 http://support.sas.com/documentation/cdl/en/etsug/60372/HTML/default/viewer.htm#etsug_tsdata_sect038.htm https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212700.htm