sas宏循环重命名变量

sas macro loop to rename variable

您好,我正在尝试使用 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.... Eg:MT20SP 重命名为 MTSp20。 当我 运行 我的循环时,没有错误,但 MilkNew 中的变量名根本没有改变。 问题出在哪里?谢谢!

您应该移动循环,使其只生成 RENAME 语句(或者甚至只生成旧=新名称对)。现在发生的事情是您不断覆盖 MilkNew,因此只有最后一个重命名有任何影响。

%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)

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

所以,这会奏效,但稍后我会解释为什么这不是执行此操作的好方法。

%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;

更好的办法是完全在宏之外生成此列表 - 查找 "generating code SAS" 以获得相关建议。


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

label _all_;

或者在宏循环中包含一个 label-clearing 语句(label <varname>; 在其中弹出与 原始 重命名前的变量名相同的变量名)解决这个问题。

如果宏的唯一目的是重命名数据集中的变量,那么为什么要用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