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
然后在 set
和 data
语句中都有它。
其次,您不应该为每次更改都执行新的数据步骤。宏中不必包含数据步骤;它们可以 运行 在数据步骤中。
例如:
%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
您好,我正在尝试使用 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
然后在 set
和 data
语句中都有它。
其次,您不应该为每次更改都执行新的数据步骤。宏中不必包含数据步骤;它们可以 运行 在数据步骤中。
例如:
%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