【问题标题】:sas macro loop to rename variablesas 宏循环重命名变量
【发布时间】:2016-01-14 19:11:22
【问题描述】:

您好,我正在尝试使用 SAS 宏循环重命名变量。

%Let t1=12Mth;
%Let t2=20;
%Let t3=30;
%Let t4=40;
%Let t5=50;
%Let t6=60;

%macro Re(time);
%Do I = 1 %to &time.; 
data MilkNew;
set Milk;
rename MT&&t&I..Sp=MTSp&&t&I.;
run;
%end;
%mend Re;
%Re(6)

这个循环意味着将 MT...Sp 重命名为 MTSp.... 例如:MT20SP 为 MTSp20。 当我运行我的循环时,没有错误,但 MilkNew 中的变量名根本没有改变。 问题出在哪里?谢谢!

【问题讨论】:

    标签: sas sas-macro


    【解决方案1】:

    如果宏的唯一目的是重命名数据集中的变量,那么为什么要使用set 语句读取数据。您的数据集可能非常小,因此您甚至没有意识到这样做的效率低下。而是使用proc datasets 中的modify 语句来完成同样的事情,但效率更高。这是一个可供您使用的替代宏。

    %macro renamevar(dsname, time);
    %local lib ds i; 
    %let lib = %sysfunc(coalescec(%scan(&dsname, -2, %str(.)), work));
    %let ds = %scan(&dsname, -1, %str(.));
    
    proc datasets lib=&lib nolist;
    modify &ds;
        rename
            %do i = 1 %to &time; 
                mt&&t&i..Sp=MTSp&&t&i.
            %end;
            ;
    quit;
    %mend;
    
    %renamevar(milk, 6);
    

    宏调用后的日志如下:

    NOTE: Renaming variable mt12MthSp to MTSp12Mth.
    NOTE: Renaming variable mt20Sp to MTSp20.
    NOTE: Renaming variable mt30Sp to MTSp30.
    NOTE: Renaming variable mt40Sp to MTSp40.
    NOTE: Renaming variable mt50Sp to MTSp50.
    NOTE: Renaming variable mt60Sp to MTSp60.
    
    NOTE: MODIFY was successful for WORK.MILK.DATA.
    NOTE: PROCEDURE DATASETS used (Total process time):
          real time           0.00 seconds
          cpu time            0.01 seconds
    

    【讨论】:

    • 非常感谢您的建议。我没有注意到效率问题。
    【解决方案2】:

    您应该移动循环,使其只生成 RENAME 语句(甚至只生成 old=new 名称对)。现在发生的事情是你不断覆盖 MilkNew,所以只有最后一个 RENAME 有任何影响。

    %macro Re(time);
     data MilkNew;
       set Milk;
     %do I = 1 %to &time.; 
       rename MT&&t&I..Sp=MTSp&&t&I.;
     %end;
     run;
    %mend Re;
    %Re(6)
    

    【讨论】:

      【解决方案3】:

      您应该已经看到循环中的 last 变量名(所以第 6 个)发生了变化。这是因为您使用相同的源数据集但不同目标重复了相同的数据步骤 - 所以每次您“忘记”在前面步骤中所做的更改。

      所以,这会奏效,不过我会在稍后解释为什么这不是一个好方法。

      %Let t1=12Mth;
      %Let t2=20;
      %Let t3=30;
      %Let t4=40;
      %Let t5=50;
      %Let t6=60;
      
      %macro Re(time);
      %Do I = 1 %to &time.; 
      data Milk;
      set Milk;
      rename MT&&t&I..Sp=MTSp&&t&I.;
      run;
      %end;
      %mend Re;
      
      data milk;
        input 
          MT12mthSP
          MT20SP
          MT30SP
          MT40SP
          MT50SP
          MT60SP
        ;
        datalines;
      12 20 30 40 50 60
      ;;;;
      run;
      
      
      %Re(6)
      

      在这里,我让它对Milk 进行所有更改并将它们保存回该数据集中。如果你想保留Milk,那么首先创建Milk_New,然后在setdata 语句中都有它。


      其次,您不应为每次更改都执行新的数据步骤。宏不必在其中包含数据步骤;它们可以在数据步中运行。

      例如:

      %macro Re(time);
        %Do I = 1 %to &time.; 
        rename MT&&t&I..Sp=MTSp&&t&I.;
        %end;
      %mend Re;
      data milk_new;
        set milk;
        %Re(6);
      run;
      

      完全在宏之外生成此列表会更好 - 查找“生成代码 SAS”以获取有关建议。


      如果您根本没有看到任何重命名,您也可能会遇到列上存在标签的问题。这不会影响您对变量名的使用,但会让人感到困惑。使用

      label _all_;
      

      或者在你的宏循环中包含一个标签清除语句(label <varname>;,你在重命名之前弹出与 original 变量名相同的变量名)来解决这个问题。

      【讨论】:

      • 感谢您的详尽回答!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      相关资源
      最近更新 更多