Loops 使用索引号的sas宏循环

Loops 使用索引号的sas宏循环,loops,sas,do-while,base,sas-iml,Loops,Sas,Do While,Base,Sas Iml,我非常渴望了解我是否能够在不使用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

我非常渴望了解我是否能够在不使用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求和这些结果。这将是迭代的。我在这里写的表格只是这个案例的一小部分


谢谢

所以基本数据步骤或过程调用已经是输入数据的循环。 如果要使用数据集作为宏调用参数值的源,则需要一个简单的驱动程序

假设您已经定义了一个宏,该宏执行一系列复杂的数据步骤和过程步骤,并接受一个或多个输入参数。然后,您可以创建参数值的数据集,并在简单的数据步骤中使用CALL EXECUTE生成对传递参数值的宏的调用。因此,如果宏%MYMACRO()是用5个位置参数定义的,并且数据集包含5个变量PARM1到PARM5和10个观察值,那么此数据步骤将生成10个宏调用

 data _null_;
    set have;
    call execute(cats('%nrstr(%mymacro)(',catx(',',of parm1-parm5),')'));
 run;

听起来,您所说的“对于a,b=e”的意思是,您希望通过a处理b=e的记录。
因此,在SAS中,如果要筛选要使用的记录,可以使用WHERE语句或选项或if语句。要处理具有相同变量集值的记录组,可以使用BY语句(或PROC SQL代码中的GROUP BY)。这是您的示例数据集

data have ;
  length a 8 b $3 c d 8 e $3 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=e时,获取c和f的最大值

第2步:将b=e时的最大值放入表中,用a将所有情况相加,其中b=e

现在,如果要对表的最大值c和f执行此操作,可以使用按a和a排序的表:

步骤1:将c和f的最大值读入宏变量中

proc sql noprint;
    select max(c), max(f)
    into :max_c, :max_f
    from have;
quit;
步骤2:对每个a的结果求和


我希望这有帮助!这只是解决问题的一种方法,但还有很多其他的好方法。这完全取决于您的目标、环境和编程风格。

您能用语言解释一下您想要什么样的输出吗?看起来你想先去。处理,但如果不了解您想要的输出,就很难给出任何建议。我只想根据列元素的观察数(如R或Matlab等)构建循环,但在SAS Base中无法实现。我不知道这是否可能。因此,基本数据步骤是基于输入数据步骤中的观察值的循环。你到底想做什么循环呢?我只是想知道如何在SAS中使用索引号来构建循环,或者是否可以像在R或Matlab中一样使用索引号?根据上面的示例数据发布预期输出。
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;
proc sql noprint;
    select max(c), max(f)
    into :max_c, :max_f
    from have;
quit;
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;