使用索引号的 sas 宏循环
sas macro loops using index numbers
我很想知道我是否可以在不使用 SAS IML 的情况下在 SAS Base 中处理此类情况;
假设我有向量
a b c d e f
1001 JPN 10,000 50% JPN 2,000
1001 EUR 12,648 100% EUR 3,000
1001 USD 15,997 50% USD 5,000
1001 JPN 20,233 20% JPN 8,000
1001 EUR 25,591 20% EUR 9,000
1001 USD 32,368 50% USD 4,000
1002 JPN 28,393 50% JPN 6,000
1002 EUR 24,906 100% EUR 4,000
1002 USD 21,847 50% USD 8,000
1002 TRY 19,164 20% JPN 6,000
1002 EUR 16,811 50% EUR 15,000
1002 USD 14,746 100% USD 52,000
1003 USD 10,000 50% XVN 8,000
%macro;
% let i = 1;
data want;
set have;
%do %while a[&i]=a[eval(&i+1)] ;
b = &i;
&i=eval(&i+1);
%end
%mend
我想做的是让 a 和 b=e 取 max(c) 和 max(f) 的差值,并将这个差值乘以 d,然后对每个不同的 a 求和这些结果。这将是迭代的。 table 我这里只是举个例子。
谢谢
因此,基本数据步骤或过程调用已经是对输入数据的循环。
如果您想使用数据集作为宏调用参数值的来源,那么您需要一个简单的驱动程序。
假设您已经定义了一个宏,该宏执行一系列复杂的数据步骤和过程步骤,并采用一个或多个输入参数。然后,您可以创建一个参数值数据集,并在一个简单的数据步骤中使用 CALL EXECUTE 生成对传递参数值的宏的调用。因此,如果宏 %MYMACRO() 定义了 5 个位置参数,并且您的数据集 HAVE 包含五个变量 PARM1 到 PARM5 和 10 个观测值,那么此数据步骤将生成 10 个宏调用。
data _null_;
set have;
call execute(cats('%nrstr(%mymacro)(',catx(',',of parm1-parm5),')'));
run;
听起来你所说的这个短语 "for a with b=e" 的意思是你想用 BY A 处理记录 WHERE B=E。
因此,在 SAS 中,如果您想过滤要使用的记录,您可以使用 WHERE 语句或选项或 IF 语句。要处理一组具有相同变量值的记录组,您可以使用 BY 语句(或 PROC SQL 代码中的 GROUP BY)。这是您的示例数据集。
data have ;
length a 8 b c d 8 e f 8;
informat c f comma32. d percent. ;
input a b c d e f ;
cards;
1001 JPN 10,000 50% JPN 2,000
1001 EUR 12,648 100% EUR 3,000
1001 USD 15,997 50% USD 5,000
1001 JPN 20,233 20% JPN 8,000
1001 EUR 25,591 20% EUR 9,000
1001 USD 32,368 50% USD 4,000
1002 JPN 28,393 50% JPN 6,000
1002 EUR 24,906 100% EUR 4,000
1002 USD 21,847 50% USD 8,000
1002 TRY 19,164 20% JPN 6,000
1002 EUR 16,811 50% EUR 15,000
1002 USD 14,746 100% USD 52,000
1003 USD 10,000 50% XVN 8,000
run;
首先,您可以使用 PROC SUMMARY 找到 C 和 F 变量的最大值。
proc summary data=have nway ;
by a ;
where b=e ;
var c f ;
output out=summary max= / autoname ;
run;
然后您可以合并回明细记录以应用计算差异并乘以百分比。
data middle ;
merge have summary ;
by a ;
if b=e ;
diff = c_max - f_max ;
product = diff * d ;
run;
然后您可以再次使用 PROC SUMMARY 求出每个组内的总和。
proc summary data=middle nway ;
by a ;
var product ;
output out=want sum=new_var ;
run;
总计
Obs a _TYPE_ _FREQ_ new_var
1 1001 0 6 67767.2
2 1002 0 5 -82624.5
感谢您的发帖!我假设你想要 b = e 时的最大值,但我会给你两个可能的解决方案以防万一。请注意,您只需要在任何 SQL 个计算组中使用一次 proc sql
,但为了清楚起见,我们只使用两次。
步骤 1:当 b[= 时,获取 c 和 f 的最大值50=] = e
proc sql noprint;
create table maxes as
select b, e,
max(c) as max_c, max(f) as max_f
from have
where upcase(b) = upcase(e)
group by b, e
;
quit;
第2步:将b = e时的最大值取到table,通过 a 总结所有情况,其中 b = e
proc sql noprint;
create table want as
select a, sum(result) as result
/* Get max values into the table.
Only interested in cases where a = b */
from(select st1.a, st1.b, st1.e,
max_c, max_f,
(max_c - max_f)*st1.d as result
from have as st1
INNER JOIN
maxes as st2
ON upcase(st1.b) = upcase(st2.b)
AND upcase(st1.e) = upcase(st2.e)
where upcase(st1.b) = upcase(st1.e) )
group by a
;
quit;
现在,如果您想对 c 和 f 的 table 最大值执行此操作,您可以这样做macro variables, the table sorted by a, by-group processing, and a Sum Statement:
第一步:将c和f的最大值读入宏变量
proc sql noprint;
select max(c), max(f)
into :max_c, :max_f
from have;
quit;
第 2 步:将每个 a
的结果相加
data want;
set have;
by a;
where upcase(b) = upcase(e);
result+( (&max_c - &max_f)*d );
if(last.a) then do;
output;
call missing(result); *Reset the sum for the next a group;
end;
keep a result;
run;
希望对您有所帮助!这只是解决问题的一种方法,但还有许多其他好方法。这完全取决于您的目标、环境和编程风格。
我很想知道我是否可以在不使用 SAS IML 的情况下在 SAS Base 中处理此类情况;
假设我有向量
a b c d e f
1001 JPN 10,000 50% JPN 2,000
1001 EUR 12,648 100% EUR 3,000
1001 USD 15,997 50% USD 5,000
1001 JPN 20,233 20% JPN 8,000
1001 EUR 25,591 20% EUR 9,000
1001 USD 32,368 50% USD 4,000
1002 JPN 28,393 50% JPN 6,000
1002 EUR 24,906 100% EUR 4,000
1002 USD 21,847 50% USD 8,000
1002 TRY 19,164 20% JPN 6,000
1002 EUR 16,811 50% EUR 15,000
1002 USD 14,746 100% USD 52,000
1003 USD 10,000 50% XVN 8,000
%macro;
% let i = 1;
data want;
set have;
%do %while a[&i]=a[eval(&i+1)] ;
b = &i;
&i=eval(&i+1);
%end
%mend
我想做的是让 a 和 b=e 取 max(c) 和 max(f) 的差值,并将这个差值乘以 d,然后对每个不同的 a 求和这些结果。这将是迭代的。 table 我这里只是举个例子。
谢谢
因此,基本数据步骤或过程调用已经是对输入数据的循环。 如果您想使用数据集作为宏调用参数值的来源,那么您需要一个简单的驱动程序。
假设您已经定义了一个宏,该宏执行一系列复杂的数据步骤和过程步骤,并采用一个或多个输入参数。然后,您可以创建一个参数值数据集,并在一个简单的数据步骤中使用 CALL EXECUTE 生成对传递参数值的宏的调用。因此,如果宏 %MYMACRO() 定义了 5 个位置参数,并且您的数据集 HAVE 包含五个变量 PARM1 到 PARM5 和 10 个观测值,那么此数据步骤将生成 10 个宏调用。
data _null_;
set have;
call execute(cats('%nrstr(%mymacro)(',catx(',',of parm1-parm5),')'));
run;
听起来你所说的这个短语 "for a with b=e" 的意思是你想用 BY A 处理记录 WHERE B=E。
因此,在 SAS 中,如果您想过滤要使用的记录,您可以使用 WHERE 语句或选项或 IF 语句。要处理一组具有相同变量值的记录组,您可以使用 BY 语句(或 PROC SQL 代码中的 GROUP BY)。这是您的示例数据集。
data have ;
length a 8 b c d 8 e f 8;
informat c f comma32. d percent. ;
input a b c d e f ;
cards;
1001 JPN 10,000 50% JPN 2,000
1001 EUR 12,648 100% EUR 3,000
1001 USD 15,997 50% USD 5,000
1001 JPN 20,233 20% JPN 8,000
1001 EUR 25,591 20% EUR 9,000
1001 USD 32,368 50% USD 4,000
1002 JPN 28,393 50% JPN 6,000
1002 EUR 24,906 100% EUR 4,000
1002 USD 21,847 50% USD 8,000
1002 TRY 19,164 20% JPN 6,000
1002 EUR 16,811 50% EUR 15,000
1002 USD 14,746 100% USD 52,000
1003 USD 10,000 50% XVN 8,000
run;
首先,您可以使用 PROC SUMMARY 找到 C 和 F 变量的最大值。
proc summary data=have nway ;
by a ;
where b=e ;
var c f ;
output out=summary max= / autoname ;
run;
然后您可以合并回明细记录以应用计算差异并乘以百分比。
data middle ;
merge have summary ;
by a ;
if b=e ;
diff = c_max - f_max ;
product = diff * d ;
run;
然后您可以再次使用 PROC SUMMARY 求出每个组内的总和。
proc summary data=middle nway ;
by a ;
var product ;
output out=want sum=new_var ;
run;
总计
Obs a _TYPE_ _FREQ_ new_var
1 1001 0 6 67767.2
2 1002 0 5 -82624.5
感谢您的发帖!我假设你想要 b = e 时的最大值,但我会给你两个可能的解决方案以防万一。请注意,您只需要在任何 SQL 个计算组中使用一次 proc sql
,但为了清楚起见,我们只使用两次。
步骤 1:当 b[= 时,获取 c 和 f 的最大值50=] = e
proc sql noprint;
create table maxes as
select b, e,
max(c) as max_c, max(f) as max_f
from have
where upcase(b) = upcase(e)
group by b, e
;
quit;
第2步:将b = e时的最大值取到table,通过 a 总结所有情况,其中 b = e
proc sql noprint;
create table want as
select a, sum(result) as result
/* Get max values into the table.
Only interested in cases where a = b */
from(select st1.a, st1.b, st1.e,
max_c, max_f,
(max_c - max_f)*st1.d as result
from have as st1
INNER JOIN
maxes as st2
ON upcase(st1.b) = upcase(st2.b)
AND upcase(st1.e) = upcase(st2.e)
where upcase(st1.b) = upcase(st1.e) )
group by a
;
quit;
现在,如果您想对 c 和 f 的 table 最大值执行此操作,您可以这样做macro variables, the table sorted by a, by-group processing, and a Sum Statement:
第一步:将c和f的最大值读入宏变量
proc sql noprint;
select max(c), max(f)
into :max_c, :max_f
from have;
quit;
第 2 步:将每个 a
的结果相加data want;
set have;
by a;
where upcase(b) = upcase(e);
result+( (&max_c - &max_f)*d );
if(last.a) then do;
output;
call missing(result); *Reset the sum for the next a group;
end;
keep a result;
run;
希望对您有所帮助!这只是解决问题的一种方法,但还有许多其他好方法。这完全取决于您的目标、环境和编程风格。