【问题标题】:looping over character values in SAS在SAS中循环字符值
【发布时间】:2013-09-06 22:24:07
【问题描述】:

在 Stata 中,您可以使用 foreach command 循环遍历字符值列表。到目前为止,我一直在尝试在 SAS 中做同样的事情,但无济于事。我正在尝试对字符列的所有值运行一系列数据和 proc 语句。我尝试了以下方法:

%let mylist = a b c; * These are all the values of a column called "code";

data mydata_@mylist; * Each element creates a new table;       
   set mydata;   
   where code=&mylist; 
   run;

我做错了什么或错过了什么?

提前致谢,

马蒂亚斯

【问题讨论】:

    标签: loops macros character sas


    【解决方案1】:

    试试这个:

    %macro loopit(mylist);
       %let n = %sysfunc(countw(&mylist));
       %do I=1 %to &n;
          %let val = %scan(&mylist,&I);
    
          data mydata_&val;
             set mydata;
             where code = "&val";
          run;
       %end;
    %mend;
    
    %let list=a b c;
    %loopit(&list);
    

    【讨论】:

    • 如果用户传递一个空列表,这将出错。指定分隔符让 COUNTW 返回 0: %sysfunc(countw(&mylist,%STR( )))
    【解决方案2】:

    基于 DomPazz 提供的修改版本:

    data mydata;
    length code $8;
    input code;
    cards;
    a
    a
    b
    c
    n
    ;
    run;
    
    %macro loopit(mylist);
        %let else=;
       %let n = %sysfunc(countw(&mylist));
        data 
       %do I=1 %to &n;
          %let val = %scan(&mylist,&I);
          mydata_&val
        %end;
            other
            ;
    
    
             set mydata;
       %do j=1 %to &n;
          %let val = %scan(&mylist,&j);
            %if &j ne 1 %then %do;
            %let else=else;
            %end;
          &else if code = "&val" then output mydata_&val;
            %if &j = &n %then %do;
            else output other;
            %end;
       %end;
       run;
    %mend;
    
    options mprint;
    %let list=a b c;
    %loopit(&list);
    

    这里我只处理一次输入数据(如果需要,为了提高效率)在一个数据步骤中创建所有输出表。 另外我正在创建一个“其他”表。如果只需要处理列表中包含代码的记录,您可以在 SET 语句下添加 WHERE 语句并省略 else 输出其他;

    【讨论】:

    • 如果 mydata 很大或者你有大量的 id 需要过滤,效率肯定更高。
    • 非常感谢,DomPazz 和 vasja! vasja 提出的解决方案似乎可行,但我仍然对字符列的某些元素有问题,其中包括 SAS 分成两个元素的破折号(“-”)。有什么建议吗?
    【解决方案3】:
    %macro getName;
    %let name = %sysfunc(translate(&val, __, -/));
    %mend;
    
    %macro loopit(mylist);
        %let else=;
         %let name=;
       %let n = %sysfunc(countw(&mylist, %str( )));
        data 
       %do I=1 %to &n;
          %let val = %scan(&mylist,&I, %str( ));
            %getName
          mydata_&name
        %end;
            other
            ;
    
    
             set mydata;
       %do j=1 %to &n;
          %let val = %scan(&mylist,&j, %str( ));
            %getName
            %if &j ne 1 %then %do;
            %let else=else;
            %end;
          &else if code = "&val" then output mydata_&name;
            %if &j = &n %then %do;
            else output other;
            %end;
       %end;
       run;
    %mend;
    
    options mprint;
    %let list=a-a b/b c-;
    %loopit(&list);
    

    此版本使用带有修饰符的COUNTWSCAN 函数仅使用空格(%str( ))作为单词分隔符。

    还使用新的宏 getName 根据 SAS 命名规则为数据集命名(注意 %let name = ; 只是在 %loopit 中提供变量以供 %getName 填充)。

    %getName 将不允许的字符转换为下划线(如果您的值相同但分隔符不同,则可能会出现名称冲突)。

    【讨论】:

      猜你喜欢
      • 2022-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      相关资源
      最近更新 更多