【问题标题】:Logic to leave loop not working SAS离开循环不工作的逻辑SAS
【发布时间】:2015-12-04 08:47:36
【问题描述】:

我想重复一些代码,改变其中一个参数并测试是否满足条件。如果满足条件,我想离开循环,如果不满足,我想继续参数的下一个值。我正在使用下面的代码,它工作正常,只是它不会在我期望的时候离开循环。尽管摘要显示条件应该已经满足,但它似乎总是解析为 False。

%macro set_downward_caps(year, in_year_tolerance, large, small, start, end, increment);
%do c = &start. %to &end. %by &increment.;
    %let nominal_down_large_&year. = %sysevalf(&large. + (&c. / 1000));
    %let nominal_down_small_&year. = %sysevalf(&small. + (&c. / 100));
    %let real_down_large_&year. = %sysevalf((1 - &&nominal_down_large_&year.) * &&rpi&year.);
    %let real_down_small_&year. = %sysevalf((1 - &&nominal_down_small_&year.) * &&rpi&year.);
    %rates(&year.);
    proc means data = output.s_&scenario. noprint nway;
        var transbill&year.;
        output out = temporary (drop = _type_ _freq_) sum=cost;
    run;
    data _null_;
        set temporary;
        call symput('cost', cost);
    run;
    data temp;
        length scenario $ 30;
        scenario = "&scenario.";
        large = &&real_down_large_&year.;
        small = &&real_down_small_&year.;
        cost = &cost.;
    run;
    data output.summary_of_caps;
        set output.summary_of_caps temp;
    run;
    %if %sysfunc(abs(&cost.)) le &in_year_tolerance. %then leave;
%end;
%mend set_downward_caps;

因此 sumary_of_caps 表包含的值表明以下条件应该已解析为真:

%if %sysfunc(abs(&cost.)) le &in_year_tolerance. %then leave;

我尝试将其粘贴在 sysevalf 中,但无济于事。

【问题讨论】:

  • 您是否尝试过设置 MPRINT、MLOGIC 和 SYMBOLGEN 选项?这应该有助于确定问题所在
  • Leave 仅用于数据步,不适用于宏。例如,您可以像这样更改它:%if %sysfunc(abs(&cost.)) le &in_year_tolerance。 %then %let c =%eval( &end.+ 1);
  • 我打开了 mlogic 和 mprint。也会打开符号生成。
  • 谢谢,我会尝试您的建议以取消休假。不幸的是,我今天在家工作,sas 运行缓慢。
  • 如果这是一个数据步骤,我建议在循环中添加一个 while 条件。在宏设置中也可以吗?

标签: loops sas


【解决方案1】:

我认为宏代码没有 LEAVE 等效项。为什么不直接使用%GOTO?或者因为您似乎想要完全离开宏,您可以使用%RETURN

此外,如果您要比较浮点数,则需要使用%SYSEVALF()%IF 语句的隐含 %EVAL() 调用将仅处理整数运算。

%if %sysevalf(%sysfunc(abs(&cost)) le &in_year_tolerance) %then %return;

为什么要在宏观逻辑中进行计算?我不确定你为什么拥有所有这些宏变量,除非 %RATES() 宏正在引用它们?但是,如果它需要它们,为什么它们不像您传入 &YEAR 那样为宏提供参数?

您当前的代码中有大量数据步骤,您可以在那里进行计算,只需设置一个标志变量,您可以使用该变量来控制是否退出循环。

%macro set_downward_caps
(year
,in_year_tolerance
,large
,small
,start
,end
,increment
);
%local c leave ;
%do c = &start %to &end %by &increment;
    %local nominal_down_large_&year ;
    %local nominal_down_small_&year ;
    %local real_down_large_&year ;
    %local real_down_small_&year ;

    %let nominal_down_large_&year. = %sysevalf(&large. + (&c. / 1000));
    %let nominal_down_small_&year. = %sysevalf(&small. + (&c. / 100));
    %let real_down_large_&year. = %sysevalf((1 - &&nominal_down_large_&year.) * &&rpi&year.);
    %let real_down_small_&year. = %sysevalf((1 - &&nominal_down_small_&year.) * &&rpi&year.);

    %rates(&year.);

    proc means data = output.s_&scenario. noprint nway;
        var transbill&year.;
        output out = temporary sum=cost;
    run;

    data temp;
        length scenario $ 30;
        scenario = "&scenario.";
        large = &&real_down_large_&year.;
        small = &&real_down_small_&year.;
        set temporary (keep=cost);
        call symputx('leave',abs(cost) le &in_year_tolerance);
        put (_all_) (=);
    run;
    data output.summary_of_caps;
        set output.summary_of_caps temp;
    run;
    %if (&leave) %then %goto quit;
%end;
%quit:
%mend set_downward_caps;

【讨论】:

  • 宏变量COST和IN_YEAR_TOLERANCE的值是多少?
  • 我已经隔离了这个问题。 SAS 将成本和年份公差视为 char vars。不过不知道怎么解决...
  • 不要使用旧的CALL SYMPUT() 函数。使用新的CALL SYMPUTX() 函数,因为它会自动删除前导空格。此外,如果您的数字很大,那么您可能需要使用自己的格式而不是默认的 BEST12. 格式。 call symputX('cost',put(cost,best32.));
  • 谢谢。遗憾的是,没有变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
相关资源
最近更新 更多