【问题标题】:Do loop with unequal increment不等增量循环
【发布时间】:2012-07-02 06:57:47
【问题描述】:

我有很多以“s”开头的 sas 数据集文件,后跟一些数字,例如 s1 s7 s13 s32 等(我有很多)。 对于每个文件,我运行一组代码,保存我的最后一个结果,然后使用以下数据集文件重新启动。通常,当我的数据集文件编号是连续的(如 s1 s2 s3 s4 s5...)时,它很容易使用,例如 %do i=1 %to 120。但是如果我想做一个不等增量的循环呢?我怎样才能做到这一点?比如%do i=1 7 13 32...。这在 MATLAB 中很容易,但在 SAS 中我不太确定如何。

【问题讨论】:

    标签: loops sas increment do-loops


    【解决方案1】:

    使您的 %do 从最低的数据集编号变为最高。然后只需检查数据集是否存在。

    %Let lib=yourlib;
    %Macro Process;
    
     %Do i = 1 %to 1000;
      %if %sysfunc(exist(&lib..s&i)) %then %do;
    
        <your code>
    
      %end;
    
     %end;
    
    %Mend process;
    %process
    

    【讨论】:

    • 您的代码将非常适合我必须通过的另一批库文件。非常感谢!
    【解决方案2】:

    %SCAN 是你的朋友。看看下面的示例代码 -

    %let nums = 1 2 4 6 13 29 32;
    
    %macro iter();
    
    %let cnt = %sysfunc(countc(&nums," "));
    %let cnt = %eval(&cnt + 1);
    %put &cnt;
    
    %do i = 1 %to &cnt;
    %put I will now process dataset s%scan(&nums,&i," ");
    %end;
    
    %mend iter;
    
    %iter()
    

    您可以修改 %put... 部分以编写 DATA 步。

    【讨论】:

    • 你能解释一下%let cnt = %sysfunc(countc(&amp;nums," ")); %let cnt = %eval(&amp;cnt + 1);背后的原因吗?据我了解,你首先计算%let nums中的总数/条目,但为什么&amp;cnt+1
    • 你问得好!这是因为,正如所写,COUNTC 函数告诉您字符串 NUMS 中有多少个空格。只要您的 NUMS 宏变量在标记之间恰好有一个空格,您就需要添加一个以查看存在多少标记。但要小心:例如,%let nums = 1 2; 有四个空格(所以 CNT 应该是五个)。 [在 %let stmt 的示例中,我似乎无法让此注释显示连续的空白。]
    • @BobDuell,好点子。是的, COUNTC 通常用于计算特定字符在字符串中出现的次数。在这里,我们必须将它与 %SYSFUNC 结合使用,因为我们将其应用于宏变量。在这种情况下,必须仔细编写 %LET nums 部分以确保没有多余的空格,或者另一个选项是使用 COMPBL(再次与 sysfunc 一起)进行额外检查。我个人更喜欢管道,并且总是把它写成 %let nums = 1|2|3;
    【解决方案3】:

    下面的例子获取数据集S1、S3和S10并对其进行处理,输出数据集NEW1、NEW3和NEW10:

    /* Example data sets */
    data s1 s3 s10;
    run;
    
    %macro mymac;
    
      /* Create 'array' of macro variables DSET1, DSET2...up to a max of DSET9999.
         Each DSETx macro variable will contain a data set number. */
      proc sql noprint;
        select compress(memname,"sS") into :dset1-:dset9999
        from sashelp.vtable
        where libname="WORK" and upcase(substr(memname,1,1))="S"
              and input(compress(memname,"sS"),8.) ne .;
      quit;
      %let numdsets=&sqlobs;
    
      /* Process data sets */    
      %do i=1 %to &numdsets.;
        data new&&dset&i.;
          set s&&dset&i.;
        run;
      %end;
    %mend mymac;
    %mymac
    

    【讨论】:

      【解决方案4】:

      您可以在正常的 do 循环中执行非顺序增量,但不能以相同的方式在宏 do 循环中执行。 SAShelp 网站上有一个解决方法。

      http://support.sas.com/kb/26/155.html

      我将首先使用以下代码将数字放入逗号分隔的宏列表中。 prxmatch 函数搜索以“S”开头、后跟一个数字的数据集名称。完成后,您可以按照 SAS 网站上的代码进行操作。

      proc sql noprint;
      select compress(upper(memname),'S') into :ds_num separated by ',' from dictionary.tables
      where libname='WORK' and prxmatch("/S\d+/",upper(memname));
      quit;
      
      %put &ds_num.;
      

      【讨论】:

        【解决方案5】:

        这是对上述 Mozan 答案的更新。我不建议使用 CountC 来计算列表中的元素。 请改用 CountW。注意以下更新:

        %let nums = 1 2 4 6 13 29 32;
        
        %macro iter();
        
        %let cnt = %sysfunc(CountW(&nums));
        %put &cnt;
        
        %do i = 1 %to &cnt;
          %put I will now process dataset s%scan(&nums,&i);
        %end;
        
        %mend iter;
        
        %iter()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-25
          相关资源
          最近更新 更多