Macros SAS和函数内部宏故障
我得到了所有的钱 我得到这个错误: 错误:函数SUM需要一个数值表达式作为参数1。 错误:函数SUM需要一个数值表达式作为参数2。 错误:函数SUM需要一个数值表达式作为参数3。 错误:在贡献表中未找到以下列:m1sales、m2sales、m3salesMacros SAS和函数内部宏故障,macros,sas,sum,proc-sql,Macros,Sas,Sum,Proc Sql,我得到了所有的钱 我得到这个错误: 错误:函数SUM需要一个数值表达式作为参数1。 错误:函数SUM需要一个数值表达式作为参数2。 错误:函数SUM需要一个数值表达式作为参数3。 错误:在贡献表中未找到以下列:m1sales、m2sales、m3sales 错误:文件WORK.QTR1.DATA不存在。如果要引用在当前SELECT语句中派生的值,则需要将计算的关键字添加到查询中 data Month1; input Name $ sales; cards; Joyce 235 Marsha 35
错误:文件WORK.QTR1.DATA不存在。如果要引用在当前SELECT语句中派生的值,则需要将
计算的
关键字添加到查询中
data Month1;
input Name $ sales;
cards;
Joyce 235
Marsha 352
Bill 491
Vernon 210
Sally 418
;
data Month2;
input Name $ sales;
cards;
Joyce 169
Marsha 281
Bill 315
Vernon 397
Sally 305
;
data Month3;
input Name $ sales;
cards;
Joyce 471
Marsha 314
Bill 394
Vernon 291
Sally 337
;
data Month4;
input Name $ sales;
cards;
Joyce 338
Marsha 259
Bill 310
Vernon 432
Sally 362
;
data Month5;
input Name $ sales;
cards;
Joyce 209
Marsha 355
Bill 302
Vernon 416
Sally 475
;
data Month6;
input Name $ sales;
cards;
Joyce 306
Marsha 472
Bill 351
Vernon 405
Sally 358
;
options sgen;
%let qtr=qtr1;
%Macro ProcSql;
Proc Sql;
%if &qtr=qtr1 %then %do;
%let month1=month1;
%let month2=month2;
%let month3=month3;
%end;
%else %if &qtr=qtr2 %then %do;
%let month1=month4;
%let month2=month5;
%let month3=month6;
%end;
%else %if &qtr=qtr3 %then %do;
%let month1=month7;
%let month2=month8;
%let month3=month9;
%end;
%else %%if &qtr=qtr4 %then %do;
%let month1=month10;
%let month2=month11;
%let month3=month12;
%end;
create table &qtr as
select &month1.name, &month1.sales as m1sales, &month2.sales as m2sales,
&month3.sales as m3sales, sum(m1sales, m2sales, m3sales) as
qtrsales
from &month1, &month2, &month3
where &month1.name=&month2.name=&month3.name;
select sum(m1sales) as m1total, sum(m2sales) as m2total, sum(m3sales) as
m3total,
sum(qtrsales) as qtrtotal
from &qtr;
%mend ProcSql;
%ProcSql;
尽早删除多个数据集。 我只是将数据连接到一个数据集中。在我的经验中,对于多个时间段(或其他变量)拥有多个相同的数据集是SAS最糟糕的反模式之一
create table &qtr as
select &month1.name
, &month1.sales as m1sales
, &month2.sales as m2sales
, &month3.sales as m3sales
, sum(calculated m1sales,calculated m2sales,calculated m3sales) as qtrsales
from &month1, &month2, &month3
where &month1.name=&month2.name
and &month1.name=&month3.name
;
使用一个数据集中的数据,操作起来就容易多了。您可以在SQL中轻松聚合它:
data sales;
set month1 (in=m1) month2 (in=m2) month3 (in=m3) month4 (in=m4) month5 (in=m5) month6 (in=m6);
if m1 then month=1;
if m2 then month=2;
if m3 then month=3;
if m4 then month=4;
if m5 then month=5;
if m6 then month=6;
qtr = ceil(month/3);
run;
或将其制成表格:
proc sql;
create table monthly_sales as
select qtr,
month,
sum(sales) as monthly_sales
from sales
group by month ;
create table quarterly_sales as
select month,
qtr,
monthly_sales,
sum(monthly_sales) as quarterly_sales
from monthly_sales
group by qtr;
quit;
或将其转置:
proc tabulate data=sales;
var sales;
class month qtr;
table qtr*(month all='total')*sales=''*sum='';
run;
使用宏生成代码,而不是控制流
如果必须使用宏,请尝试在数据步骤中使用宏生成代码,而不是在多个数据集上循环。(宏应该用来生成代码,这就是它们的设计目的)。它们经常被滥用作为程序控制结构的代理,这通常会导致无法维护的混乱局面)
在这里,我使用宏生成用于连接月份的数据步骤,其中月份数是一个变量:
proc sort data=sales; by name;
proc transpose data=sales out=sales_wide;
by name;
var sales;
id month;
run;
如果您使用
options mprint
可以看到生成的代码与上述代码相同。您的代码将更易于理解和维护,如果您使用的数据集包含一个月变量,则无需使用宏。是的,谢谢。但我得到了这个数据集和一系列问题,你确定销售是一个数字变量吗?
%macro myset(months);
set %do i=1 %to &months; month&i (in=m&i) %end; ;
%do i=1 %to &months;
if m&i then month=&i;
%end;
%mend;
data sales;
%myset(months=6);
qtr = ceil(month/3);
run;