【问题标题】:sas macro loops using index numbers使用索引号的 sas 宏循环
【发布时间】:2015-09-18 11:09:51
【问题描述】:

我非常想知道我是否可以在不使用 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

我想做的是让 b=e 的 a 取 max(c) 和 max(f) 的差,并将这个差乘以 d,然后对每个不同的 a 求和这些结果。这将是迭代的。我在这里组成的表格只是案例的一个小代表。

谢谢

【问题讨论】:

  • 你能用文字解释你想要什么输出吗?看起来你想先。处理,但如果不了解您想要的输出,就很难给出任何建议。
  • 我只想根据 R 或 Matlab 等列中元素的观察数量来构建循环,但我无法在 SAS Base 中做到这一点。我想知道这是否可能。
  • 所以基本数据步骤是基于输入数据步骤中的观察的循环。你到底想循环什么?
  • 我只想知道如何通过在 SAS 中使用索引号来构建循环,或者是否可以像在 R 或 Matlab 中一样使用索引号?
  • 根据上面的示例数据发布预期输出。

标签: loops sas do-while base sas-iml


【解决方案1】:

感谢您的发帖!我假设你想要 b = e 时的最大值,但我会给你两种可能的解决方案以防万一。请注意,您只需在任何 SQL 计算组中使用一次proc sql,但为了清楚起见,我们只需要使用两次。

第 1 步:当 b = ec 和 f 的最大值/strong>

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;

第二步:将b = e时的最大值取入表中,用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;

现在,如果您想对 cf 的表最大值执行此操作,您可以使用 macro variables 执行此操作,该表按 排序一个by-group processing和一个Sum Statement

第一步:将cf的最大值读入宏变量

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;

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

【讨论】:

    【解决方案2】:

    听起来您所说的“for a with b=e”的意思是您希望 BY A 处理 WHERE 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
    

    【讨论】:

      【解决方案3】:

      因此,基本数据步骤或 proc 调用已经是对输入数据的循环。 如果您想使用数据集作为宏调用的参数值的来源,那么您需要一个简单的驱动程序。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多