【问题标题】:SAS macro - rename variables using their label values as their new variable namesSAS 宏 - 使用标签值作为新变量名重命名变量
【发布时间】:2018-08-09 16:42:05
【问题描述】:

我想生成一个将数据集的变量名称转换为变量标签的宏。我打算将此宏应用于无法手动更改变量名称的大型数据集。

我遇到了这个code online from the SAS website,它看起来很有希望,但产生了错误。我稍作修改以消除一些错误。它现在适用于他们的示例数据集,但不适用于我的。对于改进此代码以使用我的示例数据集的任何帮助,我们将不胜感激!

SAS 示例数据集(使用代码):

data t1;  
   label x='this_x' y='that_y';
   do x=1,2;
      do y=3,4;
         z=100;
         output;
      end;
   end;
run;

我的示例数据集(不适用于代码):

data t1;
   input number group;
   label number = number_lab group = group_lab;
   datalines;
1 1
1 .
2 1
2 .
3 2
3 .
4 1
4 .
5 2
5 .
6 1
6 .
;
run;

代码:

%macro chge(dsn);                                                                                                                       
   %let dsid=%sysfunc(open(&dsn));                                                                                                        
   %let cnt=%sysfunc(attrn(&dsid,nvars));                                                                                                 
   %do i= 1 %to &cnt;                                                                                                                    
      %let var&i=%sysfunc(varname(&dsid,&i));                                                                                             
      %let lab&i=%sysfunc(varlabel(&dsid,&i));                                                                                            
      %if lab&i = %then %let lab&i=&&var&i;                                                                                            
   %end;                                                                                                                                 
   %let rc=%sysfunc(close(&dsid));                                                                                                        
                                                                                                                                        
   proc datasets;                                                                                                                          
      modify &dsn;                                                                                                                           
      rename                                                                                                                                 
      %do j = 1 %to &cnt;                                                                                                                  
         %if &&var&j ne &&lab&j %then %do;                                                                                                   
            &&var&j=&&lab&j                                                                                                                    
         %end;                                                                                                                               
      %end;                                                                                                                               
   quit;                                                                                                                                   
   run;                                                                                                                                    
                                                                                                                                        
%mend chge;  

%chge(t1)

proc contents;                                                                                                                          
run;

我的代码产生以下错误消息:

错误 73-322:需要一个 =。

ERROR 76-322:语法错误,语句将被忽略。

【问题讨论】:

    标签: sas label rename sas-macro


    【解决方案1】:

    主要是你没有用分号结束 RENAME 语句。但看起来您的 RUN 和 QUIT 语句的顺序错误。

    但请注意,不需要复杂的 %sysfunc() 宏代码来获取名称和标签列表。由于您已经在生成 PROC DATASETS 步骤,因此您的宏也可以生成其他 SAS 代码。这样你的宏就会更清晰,更容易调试。

    %macro chge(dsn);
      %local rename ;
       proc contents data=&dsn noprint out=__cont; run;
       proc sql noprint ;
         select catx('=',nliteral(name),nliteral(label))
           into :rename separated by ' '
           from __cont
           where name ne label  and not missing(label)
         ;
       quit;
     %if (&sqlobs) %then %do;
       proc datasets nolist;
          modify &dsn;
          rename &rename ;
       run;
       quit;
    %end;
    %mend chge;
    

    如果重命名对的列表太长而无法放入单个宏变量,那么您可以求助于使用 PROC SQL 生成两个系列的宏变量,然后添加回您的 %DO 循环。

    这是对您的示例文件进行测试的 SAS 日志。

    4156   %chge(t1);
    MPRINT(CHGE):   proc contents data=t1 noprint out=__cont;
    MPRINT(CHGE):   run;
    
    NOTE: The data set WORK.__CONT has 2 observations and 41 variables.
    NOTE: PROCEDURE CONTENTS used (Total process time):
          real time           0.08 seconds
          cpu time            0.01 seconds
    
    
    MPRINT(CHGE):   proc sql noprint ;
    MPRINT(CHGE):   select catx('=',nliteral(name),nliteral(label)) into :rename
    separated by ' ' from __cont where name ne label and not missing(label) ;
    MPRINT(CHGE):   quit;
    NOTE: PROCEDURE SQL used (Total process time):
          real time           0.04 seconds
          cpu time            0.00 seconds
    
    
    MPRINT(CHGE):   proc datasets nolist;
    MPRINT(CHGE):   modify t1;
    MPRINT(CHGE):   rename group=group_lab number=number_lab ;
    NOTE: Renaming variable group to group_lab.
    NOTE: Renaming variable number to number_lab.
    MPRINT(CHGE):   run;
    NOTE: MODIFY was successful for WORK.T1.DATA.
    MPRINT(CHGE):   quit;
    NOTE: PROCEDURE DATASETS used (Total process time):
          real time           0.12 seconds
          cpu time            0.00 seconds
    

    请注意,如果我现在尝试在修改后的数据集上再次运行它,它不会重命名任何内容。

    4157   %chge(t1);
    MPRINT(CHGE):   proc contents data=t1 noprint out=__cont;
    MPRINT(CHGE):   run;
    
    NOTE: The data set WORK.__CONT has 2 observations and 41 variables.
    NOTE: PROCEDURE CONTENTS used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
    
    
    MPRINT(CHGE):   proc sql noprint ;
    MPRINT(CHGE):   select catx('=',nliteral(name),nliteral(label)) into :rename
    separated by ' ' from __cont where name ne label and not missing(label) ;
    NOTE: No rows were selected.
    MPRINT(CHGE):   quit;
    NOTE: PROCEDURE SQL used (Total process time):
          real time           0.08 seconds
          cpu time            0.00 seconds
    

    【讨论】:

    • 感谢您的建议。这不适用于我的任何一个数据集,产生此错误:2 modify &dsn;重命名 &rename ;跑;辞职; - 73 错误 73-322:期待 =。
    • 我怀疑真正的错误在生成宏变量列表的程序中更高。我已经更新了答案中的代码,为标签等的空值添加更多保护。
    • 您更新后的代码已经成功,处理缺失值。感谢您的帮助,以及对大变量名称的警告(如果名称大于 32 个字符,它确实会失败)
    • 您可以通过将nliteral(label) 更改为nliteral(substr(label,1,32)) 来处理更长的标签,但这不会解决标签被截断时目标名称重复导致的任何问题。或者标签值中的无效字符会使它们无法用作名称,即使使用 validvarname=any 选项也是如此。
    【解决方案2】:

    你在这里缺少一个分号:

    &&var&j=&&lab&j
    

    如果您仍然收到错误,请打开这些选项并让我们知道错误发生的位置。

    options symbolgen mprint;
    

    【讨论】:

    • 实际上缺少的分号并没有出现在该行上,因为该行运行 &cnt 次。分号需要在quit 语句之前。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 2019-12-01
    相关资源
    最近更新 更多