首页 文章

proq sql宏;循环列表

提问于
浏览
1

我有一个宏,在给定的数据集中查找变量名称 . 如果缺少宏正在查找的变量名称,则缺少的变量名称将添加到表中:

%macro miss(ds, var);
    %local rc dsid result;
    %let dsid=%sysfunc(open(&ds));
    %if %sysfunc(varnum(&dsid,&var)) > 0 %then %do;
        %put &var present;
    %end;
    %else %do;
        insert into work.compare(missing) values("&var")
    %end;
%mend;

proc datasets library=work nolist nodetails;
    delete compare;
run;

proc sql;
    create table work.compare (missing char(15));
%miss(ctr.panup_in, u_name);
quit;

proc print noobs data=work.compare;
run;

需要为55个不同的变量名运行此检查 . 目前,我只把每一个列为一个

%miss(ctr.panup_in, varname);

线 .

出于实际原因,我想将变量列表指定为列表,例如%let dictionary = var1 var2 var3等 . 我现在的斗争是找到宏循环变量列表的方法 . 到目前为止我尝试过的所有内容都会导致“Stament is not valid”错误

insert into work.compare(missing) values("&var")

命令 .

有没有人对如何做到这一点有任何建议?

4 回答

  • 1

    这循环了一组变量,其中变量用“|”分隔 . 也可以在扫描功能中使用和指定任何其他分隔符 .

    %macro loop(varlist);
    %let i=1;
    %do %while (%scan(&varlist, &i, |) ^=%str());
    %let var=%scan(&varlist, &i, |); 
    %put &var;
    
    *rest of SAS code goes here;
    
    *Increment counter;
    %let i=%eval(&i+1);
    %end;
    %mend;
    %let temp=a|b|c|d|e;
    %loop(&temp);
    
  • 1

    你真的需要检查吗?您可以定义要删除的所有变量的零obs数据集,如果它们丢失则使用未执行的SET来包含它们 .

    *All variables that you might want to add;
    data master0;
       attrib a length=8;
       attrib b length=$15;
       attrib c length=$15;
       stop;
       call missing(of _all_);
       run;
    
    *Subset of the variable in master0;
    data a;
       do a = 1 to 10;
          output;
          end;
       retain X 1;
       run;
    
    *Create new data with master + a variables;
    data a_all;
       set a;
       if 0 then set master0;
       run;
    proc print;
       run;
    

    您可以使用修改来删除不需要的变量,以使用所有变量更新到主服务器 .

    *Create new data with with only wanted variables from master0;
    data a_all;
       stop;
       set master0;
       run;
    data a_all;
       if 0 then modify a_all;
       set a;
       output;
       run;
    
  • 1

    另一个选择是将变量存储在表中 - 它们可能已经存在于一个表中 . 也许是dictionary.columns?

    事实上,你可以通过dictionary.columns简单地完成整个过程 . 例如:

    %let varlist=name age novar;
    
    data values_to_check;
      length name $32;
      do _i = 1 to countw("&varlist.");
        name= scan("&varlist.",_i);
        output;
      end;
    run;
    
    
    proc sql;
    
      create table compare as
        select V.name as missing
        from values_to_check V
        left join
         (Select * from dictionary.columns 
          where memname='CLASS' and libname='SASHELP') D      
          on upcase(V.name)=upcase(D.name)
        where D.name is null
        ;
      quit;
    

    如果您不必创建数据集(如果它已经存在),则这当然更容易 - 或者作为另一个数据集中存在的变量列表,或者直接通过数据或类似创建数据集 . 可能的情况是,您有一些具有此信息的数据,不仅仅是硬编码的%let语句 .

    一个示例,用于标识 CLASSFIT 中的变量,而不是 CLASS 中的变量(均在 SASHELP 库中):

    proc sql;    
      create table compare as
        select V.name as missing
        from  
          (Select * from dictionary.columns 
          where memname='CLASSFIT' and libname='SASHELP')  V
        left join
         (Select * from dictionary.columns 
          where memname='CLASS' and libname='SASHELP') D      
          on upcase(V.name)=upcase(D.name)
        where D.name is null
        ;
      quit;
    
  • 0

    如果您确实需要一个名称不在数据集中的表,那么您可以使用数据步骤并消除使用宏或PROC SQL的复杂性 .

    %let ds=sashelp.class;
    %let varlist=age sex gender ;
    data compare;
      length missing $32 ;
      dsid=open("&ds");
      do i=1 to countw("&varlist");
        missing = scan("&varlist",i);
        if not varnum(dsid,missing) then output;
      end;
      rc=close(dsid);
      stop;
      keep missing;
    run;
    

    现在,宏解决方案可能有用的地方是,如果您想传入列表并获取另一个列表,而不生成任何代码 .

    %macro miss(ds, varlist);
    %local dsid i var result;
    %let dsid=%sysfunc(open(&ds));
    %if (&dsid) %then %do;
      %do i=1 %to %sysfunc(countw(&varlist));
        %let var=%scan(&varlist,&i);
        %if not %sysfunc(varnum(&dsid,&var)) %then %let result=&result &var;
      %end;
      %let rc=%sysfunc(close(&dsid));
    %end;
    %else %let result=&varlist;
    &result.
    %mend miss;
    

    这样你就可以在语句中间调用宏,就像函数调用一样 .

    %put Missing variables are: %miss(sashelp.class,age sex gender);
    

相关问题