Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 有没有办法在SAS宏中使用嵌套循环,一个用于年,一个用于月,以及在年中开始和停止?_Loops_Nested_Sas - Fatal编程技术网

Loops 有没有办法在SAS宏中使用嵌套循环,一个用于年,一个用于月,以及在年中开始和停止?

Loops 有没有办法在SAS宏中使用嵌套循环,一个用于年,一个用于月,以及在年中开始和停止?,loops,nested,sas,Loops,Nested,Sas,多年来,我一直在SAS中使用嵌套循环一次提取少量数据,然后处理/子集数据,然后在宏末尾附加到数据集,但我总是必须提取所有月份(或季度),然后再将最终数据集子集。我想做的是自动删除数据的开始和结束部分。在我下面的例子中,我想把2017年的1月和2020年的12月分开。我用于子集的数据中的日期变量存储为字符变量,格式为“yyyy-mm-dd”。当我运行这段代码时,它仍然显示我不想看到的月份。有人看到我丢失的任何明显的东西吗 %let year1=2017-02; *I'm currently usi

多年来,我一直在SAS中使用嵌套循环一次提取少量数据,然后处理/子集数据,然后在宏末尾附加到数据集,但我总是必须提取所有月份(或季度),然后再将最终数据集子集。我想做的是自动删除数据的开始和结束部分。在我下面的例子中,我想把2017年的1月和2020年的12月分开。我用于子集的数据中的日期变量存储为字符变量,格式为“yyyy-mm-dd”。当我运行这段代码时,它仍然显示我不想看到的月份。有人看到我丢失的任何明显的东西吗

%let year1=2017-02; *I'm currently using dates in this format, but the data is too big to pull long periods of data;
%let year2=2020-11;

data _null_;  *taking apart the pieces and getting start/stop year and months assigned as macro vars.;
  year1="&year1";
  year2="&year2";
  y1=substr(year1,1,4);
  y2=substr(year2,1,4);
  m1=substr(year1,6,2);
  m2=substr(year2,6,2);
  call symput('m1',m1);
  call symput('m2',m2);
  call symput('y1',y1);
  call symput('y2',y2);
  put "&y1";
  put "&y2";
  put "&m1";
  put "&m2";
run;

%macro test1234;
%do yr=&y1 %to &y2;  *starting with year;
%do mo=1 %to 12; * nested do loop is for month, and trying to only keep month/year combos within the start/stop dates;
  %if ((yr ne &y1) AND (yr ne &y2)) OR (yr=&y1 and mo ge &m1) OR (yr=&y2 AND mo le &m2) %then %do; 
** for line above: 1st condition: if not a start or stop year, 2nd: start year and not before start month, 3rd, stop year, and not after stop month.;
data _null_; * viewing all the macro variables;
  put "LoopYear" "&yr";
  put "LoopMonth" "&mo";
  put "FirstMonth" "&m1";
  put "FirstYear" "&y1";
  put "LastMonth" "&m2";
  put "LastYear" "&y2";
run;
%end;
%else %do; %end;
%end; %end; 
%mend test1234;
%test1234;

我的建议是重构代码,使用这两个参数并按月数循环。然后,要更改代码以排除端点,可以根据需要通过更改间隔来调整%DO循环

  • 将年份1转换为SAS日期

  • 将第2年转换为SAS日期

  • 计算这两个日期之间的月数

  • 循环计算月数

    %macro loop_dates(year1=, year2=);
    
    *Convert dates to start and end dates in the SAS format;
     %let start_date = %sysfunc(inputn(&year1.-01, yymmdd10.)); /*1*/
     %let end_date = %sysfunc(inputn(&year2.-01, yymmdd10.)); /*2*/
    
     *Calculate the number of months between the two dates;
     %let nMonths = %sysfunc(intck(month, &start_date, &end_date, c)); /*3*/
    
     *check macro variables, not really needed;
     %put %sysfunc(putn(&start_date, date9.));
     %put %sysfunc(putn(&end_date, date9.));
     %put &nMonths;
     *loop over the number of months and create macro variables as needed;
    
     %do i=0 %to &nMonths; /*4*/
         *increment date by loop counter i;
         %let newDate = %sysfunc(intnx(month, &start_date, &i, s));
    
        *calculate your macro variables needed for loop, not sure why???;
         %let yr = %sysfunc(year(&newDate.));
         %let mo = %sysfunc(month(&newDate.));
         %let m1 = %sysfunc(month(&start_date.));
         %let y1 = %sysfunc(year(&start_date.));
         %let m2 = %sysfunc(month(&end_date.));
         %let y2 = %sysfunc(year(&end_date.));
    
         *test macro variables, not needed;
         %put "LoopYear" "&yr";
         %put "LoopMonth" "&mo";
         %put "FirstMonth" "&m1";
         %put "FirstYear" "&y1";
         %put "LastMonth" "&m2";
         %put "LastYear" "&y2";
     %end;
    
     %mend loop_dates;
    
     *Call macro with the date intervals rather than use an un-parameterized macro
     %loop_dates(year1=2017-02, year2=2020-11);
    
  • 这包括2017-02年开始和2020-11年结束。若要将其更改为不包括终点,请通过增加起点和终点来更改%DO。现在它从1开始,在nMonths-1结束

    发件人:

    致:


    在您的子分类声明中,您缺少&yr和&mo前面的符号。也就是说,你应该改变:

    %if((yr东北和y1)和(yr东北和y2))或(yr=&y1和mo ge&m1)或(yr=&y2和mo le&m2)

    %if(&yr ne&y1和&yr ne&y2)或(&yr=&y1和&mo ge&m1)或(&yr=&y2和&mo le&m2)

    然后,您将排除第一个月和最后一个月,正如您所期望的那样


    也就是说,如果使用数字日期而不是字符变量,程序无疑会大大简化。

    这是永久性的变化吗,ie是否要将宏更改为始终或有条件地排除endpoint/startpoint间隔?我看不出您是如何使用宏变量来实际子集数据的。您的问题是如何将值从一个月转换为上一个月还是下一个月?因此2017-01年进入2017-02年。还是2020-12年到2020-11年?为什么不至少在循环中使用实际的日期值呢?数据在SQL数据库中,有几个表是我按日期提取的,所有表都具有相同的日期结构(字符“2020-07-08”),所以我使用“where”&year1“le substr(tdate,1,7)le“&year2”;”如果我提取长达一年的数据,我的方法可以很好地工作,但在提取更大的日期窗口时,我的内存不足。到目前为止,我已经通过一次按年份运行并将它们组合在一起解决了这个问题,但是越来越多的人要求我运行更长的周期,所以我想转换我的宏,以便能够在不需要额外步骤的情况下拉长周期或短周期。
    %do i=0 %to &nMonths;
    
    %do i=1 %to &nMonths-1;