如何在 PROC SQL 中使用 MACRO 在 SAS 中创建连续变量
How to use MACRO in PROC SQL to create consecutive variables in SAS
我想使用 MACRO 简化 PROC SQL 中的 SAS 代码。
我已经通过使用 MARCO 替换 YYMM 在数据步骤中取得了成功。
YYMM 连续数月。
示例数据和我的原始代码如下。
data work.allredeem;
input no_code BONUS_0907 BONUS_0908 BONUS_0909 BONUS_0910 BONUS_0911 BONUS_0912 BONUS_1001 BONUS_1002 BONUS_1003 BONUS_1004 BONUS_1005 BONUS_1006 BONUS_1007 BONUS_1008 BONUS_1009 BONUS_1010 BONUS_1011 BONUS_1012;
DATALINES;
1 9 7 6 9 9 5 2 1 4 4 9 5 4 1 9 3 3 7
1 3 1 4 1 5 7 8 6 1 1 8 1 1 3 9 7 1 7
2 8 3 10 8 5 6 1 9 5 2 4 8 4 2 3 8 6 1
2 5 1 8 8 6 2 2 6 6 3 4 4 5 4 8 8 2 4
3 7 4 1 3 2 7 9 5 6 8 10 3 2 5 7 10 10 6
4 7 3 6 5 8 6 9 9 3 6 1 3 4 6 5 3 4 9
5 2 1 8 2 4 3 8 8 1 9 4 9 6 10 7 5 6 8
5 10 10 4 10 4 3 7 4 8 7 1 5 1 1 9 4 6 10
5 8 10 6 9 6 5 2 8 7 6 4 1 5 9 5 6 7 6
6 6 3 1 2 6 6 10 7 9 9 3 5 2 6 6 8 6 5
7 9 5 1 9 5 9 10 3 4 10 3 7 1 6 3 10 3 6
7 4 5 8 3 2 3 8 10 2 10 3 9 4 2 2 7 1 9
7 7 4 2 4 5 1 3 2 2 1 5 4 9 2 1 9 3 3
7 10 6 5 10 5 7 9 2 2 3 8 9 6 10 3 2 10 4
7 7 9 1 6 6 3 8 8 7 10 10 9 7 4 1 1 2 2
;
RUN;
PROC SQL;
create table allredeem2 as
SELECT no_code,
sum(BONUS_0907) AS redeemNum0907,
sum(BONUS_0908)AS redeemNum0908,
sum(BONUS_0909)AS redeemNum0909,
sum(BONUS_0910)AS redeemNum0910,
sum(BONUS_0911)AS redeemNum0911,
sum(BONUS_0912)AS redeemNum0912,
sum(BONUS_1001)AS redeemNum1001,
sum(BONUS_1002)AS redeemNum1002,
sum(BONUS_1003)AS redeemNum1003,
sum(BONUS_1004)AS redeemNum1004,
sum(BONUS_1005)AS redeemNum1005,
sum(BONUS_1006)AS redeemNum1006,
sum(BONUS_1007)AS redeemNum1007,
sum(BONUS_1008)AS redeemNum1008,
sum(BONUS_1009)AS redeemNum1009,
sum(BONUS_1010)AS redeemNum1010,
sum(BONUS_1011)AS redeemNum1011,
sum(BONUS_1012)AS redeemNum1012
FROM allredeem
GROUP BY no_code;
QUIT;
我尝试如下使用 MACRO,但它不起作用。
%MACRO sub(year);
PROC SQL;
create table allredeem2 as
SELECT no_code, sum(BONUS_&year) AS redeemNum&year
FROM allredeem
GROUP BY no_code;
QUIT;
%MEND sub;
%sub(0907)
%sub(0908)
%sub(0909)
%sub(0910)
%sub(0911)
%sub(0912)
%sub(1001)
%sub(1002)
%sub(1003)
%sub(1004)
%sub(1005)
%sub(1006)
%sub(1007)
%sub(1008)
%sub(1009)
%sub(1010)
%sub(1011)
%sub(1012)
提前致谢。
宏不起作用的原因是因为您在宏调用中创建了相同的 table,即您在每个宏调用中都覆盖了 table。在最终 table 中,您将 no_code 和属于 1012 的值。这在 proc 中很容易处理。
在 SQL 中处理此问题的一种方法是使用 dictionary.columns,如下所示。
proc sql noprint;
select
'sum('|| trim(name)||') as redeemNum'||compress(name,,'kd') into :sum separated by
','
from dictionary.columns
where libname ='WORK'
and upcase(memname) = upcase('allredeem')
and upcase(type) ='NUM'
and upcase(name) ne upcase("no_code");
%put &count;
proc sql;
create table want as
select no_code, &sum
from allredeem
group by no_code;
另一个简单的处理方法是在 datastep 中使用数组和求和语句。
proc sort data=allredeem;
by no_code;
run;
data want;
set allredeem;
by no_code;
array bonus(*) BONUS0907 - BONUS0912 BONUS1001 - BONUS1012;
array redeem(*) redeemNum0907 - redeemNum0912 redeemNum1001 - redeemNum1012;
do i = 1 to dim(bonus);
if first.no_code then redeem(i) = bonus(i);
else redeem(i) +bonus(i);
end;
drop bonus: i;
if last.no_code;
run;
我想使用 MACRO 简化 PROC SQL 中的 SAS 代码。 我已经通过使用 MARCO 替换 YYMM 在数据步骤中取得了成功。 YYMM 连续数月。 示例数据和我的原始代码如下。
data work.allredeem;
input no_code BONUS_0907 BONUS_0908 BONUS_0909 BONUS_0910 BONUS_0911 BONUS_0912 BONUS_1001 BONUS_1002 BONUS_1003 BONUS_1004 BONUS_1005 BONUS_1006 BONUS_1007 BONUS_1008 BONUS_1009 BONUS_1010 BONUS_1011 BONUS_1012;
DATALINES;
1 9 7 6 9 9 5 2 1 4 4 9 5 4 1 9 3 3 7
1 3 1 4 1 5 7 8 6 1 1 8 1 1 3 9 7 1 7
2 8 3 10 8 5 6 1 9 5 2 4 8 4 2 3 8 6 1
2 5 1 8 8 6 2 2 6 6 3 4 4 5 4 8 8 2 4
3 7 4 1 3 2 7 9 5 6 8 10 3 2 5 7 10 10 6
4 7 3 6 5 8 6 9 9 3 6 1 3 4 6 5 3 4 9
5 2 1 8 2 4 3 8 8 1 9 4 9 6 10 7 5 6 8
5 10 10 4 10 4 3 7 4 8 7 1 5 1 1 9 4 6 10
5 8 10 6 9 6 5 2 8 7 6 4 1 5 9 5 6 7 6
6 6 3 1 2 6 6 10 7 9 9 3 5 2 6 6 8 6 5
7 9 5 1 9 5 9 10 3 4 10 3 7 1 6 3 10 3 6
7 4 5 8 3 2 3 8 10 2 10 3 9 4 2 2 7 1 9
7 7 4 2 4 5 1 3 2 2 1 5 4 9 2 1 9 3 3
7 10 6 5 10 5 7 9 2 2 3 8 9 6 10 3 2 10 4
7 7 9 1 6 6 3 8 8 7 10 10 9 7 4 1 1 2 2
;
RUN;
PROC SQL;
create table allredeem2 as
SELECT no_code,
sum(BONUS_0907) AS redeemNum0907,
sum(BONUS_0908)AS redeemNum0908,
sum(BONUS_0909)AS redeemNum0909,
sum(BONUS_0910)AS redeemNum0910,
sum(BONUS_0911)AS redeemNum0911,
sum(BONUS_0912)AS redeemNum0912,
sum(BONUS_1001)AS redeemNum1001,
sum(BONUS_1002)AS redeemNum1002,
sum(BONUS_1003)AS redeemNum1003,
sum(BONUS_1004)AS redeemNum1004,
sum(BONUS_1005)AS redeemNum1005,
sum(BONUS_1006)AS redeemNum1006,
sum(BONUS_1007)AS redeemNum1007,
sum(BONUS_1008)AS redeemNum1008,
sum(BONUS_1009)AS redeemNum1009,
sum(BONUS_1010)AS redeemNum1010,
sum(BONUS_1011)AS redeemNum1011,
sum(BONUS_1012)AS redeemNum1012
FROM allredeem
GROUP BY no_code;
QUIT;
我尝试如下使用 MACRO,但它不起作用。
%MACRO sub(year);
PROC SQL;
create table allredeem2 as
SELECT no_code, sum(BONUS_&year) AS redeemNum&year
FROM allredeem
GROUP BY no_code;
QUIT;
%MEND sub;
%sub(0907)
%sub(0908)
%sub(0909)
%sub(0910)
%sub(0911)
%sub(0912)
%sub(1001)
%sub(1002)
%sub(1003)
%sub(1004)
%sub(1005)
%sub(1006)
%sub(1007)
%sub(1008)
%sub(1009)
%sub(1010)
%sub(1011)
%sub(1012)
提前致谢。
宏不起作用的原因是因为您在宏调用中创建了相同的 table,即您在每个宏调用中都覆盖了 table。在最终 table 中,您将 no_code 和属于 1012 的值。这在 proc 中很容易处理。
在 SQL 中处理此问题的一种方法是使用 dictionary.columns,如下所示。
proc sql noprint;
select
'sum('|| trim(name)||') as redeemNum'||compress(name,,'kd') into :sum separated by
','
from dictionary.columns
where libname ='WORK'
and upcase(memname) = upcase('allredeem')
and upcase(type) ='NUM'
and upcase(name) ne upcase("no_code");
%put &count;
proc sql;
create table want as
select no_code, &sum
from allredeem
group by no_code;
另一个简单的处理方法是在 datastep 中使用数组和求和语句。
proc sort data=allredeem;
by no_code;
run;
data want;
set allredeem;
by no_code;
array bonus(*) BONUS0907 - BONUS0912 BONUS1001 - BONUS1012;
array redeem(*) redeemNum0907 - redeemNum0912 redeemNum1001 - redeemNum1012;
do i = 1 to dim(bonus);
if first.no_code then redeem(i) = bonus(i);
else redeem(i) +bonus(i);
end;
drop bonus: i;
if last.no_code;
run;