SAS宏从一个变量中提取多个变量

SAS宏从一个变量中提取多个变量,sas,sas-macro,Sas,Sas Macro,我找不到一个起点,因为我对SAS真的很陌生 我有一个如下所示的数据集: customer id number volume 1 ab 10 5 1 cd 7 3 2 xy 15 2 2 ab 3 50 customer id number volume ab cd xy 1 ab 10 5 50 . . 1 cd 7 3 .

我找不到一个起点,因为我对SAS真的很陌生

我有一个如下所示的数据集:

customer id number volume
1        ab  10     5
1        cd  7      3
2        xy  15     2
2        ab  3      50
customer id number volume ab cd xy
1        ab  10     5     50 .  .
1        cd  7      3     .  21 .
2        xy  15     2     .  .  30
2        ab  3      50    150 . .
我想创建一个新的数据集,其中每个distint id都需要一个新变量。 在id出现的行中,数字和体积应在新变量中相乘。新数据集应如下所示:

customer id number volume
1        ab  10     5
1        cd  7      3
2        xy  15     2
2        ab  3      50
customer id number volume ab cd xy
1        ab  10     5     50 .  .
1        cd  7      3     .  21 .
2        xy  15     2     .  .  30
2        ab  3      50    150 . .

有人有主意吗?也许解决方案很简单,但每一条评论都很受欢迎,因为我对SAS真的很陌生。

无需使用宏。数组应该为您处理这个问题

data want;
set have;
array flagvars ab cd xy;  *an array of your 3 new variables;
do _i = 1 to dim(flagvars);  *iterate one to the dimension of the array (# of vars in it);
  if upcase(vname(flagvars[_i])) = upcase(id) then flagvars[_i] = number*volume;  *if the name of the variable is identical to the id value, set that member of the array to the desired value;
end;
run;
如果有很多宏变量,可以使用数组变量列表构造宏变量:

proc sql;
select distinct id into :idlist separated by ' ' from have;
quit;
然后使用

array flagvars &idlist.;
代替写出来的清单

或者,如果预先创建number*volume变量,则可以进行转置

data have;
input customer id $ number volume;
total = number*volume;
datalines;
1        ab  10     5
1        cd  7      3
2        xy  15     2
2        ab  3      50
;;;;;
run;
proc sort data=have;
by customer id;
run;
proc transpose data=have out=have_t;
by customer id;
copy number volume;
var total;
id id;
run;

ID语句根据参数命名变量。在本例中,ID.Copy附加了转置中未使用的变量。您必须按客户id排序,才能使其正常工作。

无需使用宏。数组应该为您处理这个问题

data want;
set have;
array flagvars ab cd xy;  *an array of your 3 new variables;
do _i = 1 to dim(flagvars);  *iterate one to the dimension of the array (# of vars in it);
  if upcase(vname(flagvars[_i])) = upcase(id) then flagvars[_i] = number*volume;  *if the name of the variable is identical to the id value, set that member of the array to the desired value;
end;
run;
如果有很多宏变量,可以使用数组变量列表构造宏变量:

proc sql;
select distinct id into :idlist separated by ' ' from have;
quit;
然后使用

array flagvars &idlist.;
代替写出来的清单

或者,如果预先创建number*volume变量,则可以进行转置

data have;
input customer id $ number volume;
total = number*volume;
datalines;
1        ab  10     5
1        cd  7      3
2        xy  15     2
2        ab  3      50
;;;;;
run;
proc sort data=have;
by customer id;
run;
proc transpose data=have out=have_t;
by customer id;
copy number volume;
var total;
id id;
run;

ID语句根据参数命名变量。在本例中,ID.Copy附加了转置中未使用的变量。您必须按客户id进行排序,才能使其正常工作。

感谢您的快速回答!但我还有一个可能很愚蠢的问题;-实际上有952个不同的ID,所以我不能直接在代码中编写它们。我有没有可能事先将它们存储在数组中?我编辑了第二个解决方案,并添加了一种自动获取列表的方法。似乎这个答案被接受了,这表明这有助于每个人快速获得答案!但我还有一个可能很愚蠢的问题;-实际上有952个不同的ID,所以我不能直接在代码中编写它们。我是否有可能事先将它们存储在数组中?我编辑了第二个解决方案,并提供了一种自动获取该列表的方法。似乎这个答案被接受了,表明这对每个人都有帮助