【问题标题】:SAS: How to assign the output value of a function-like macro?SAS:如何分配类似函数的宏的输出值?
【发布时间】:2014-10-01 20:54:32
【问题描述】:

我是使用 SAS 的新手,我很难尝试将类似函数的宏的输出值分配给宏变量。测试后,我检查了该值是否计算正确,但是一旦我尝试分配它,程序就会崩溃。在这里你可以找到代码

%MACRO TP_BULLET(ZCURVE,TAU,YF=1);

    /* KEEP ONLY THE ZERO CURVE UNTIL MATURITY*/
    DATA _TEMP;
        SET &ZCURVE;
        IF MATURITY > &TAU  THEN DELETE;
    RUN;

    PROC SQL NOPRINT;
        SELECT DISTINCT 1- DF
            INTO :NUME
        FROM _TEMP
        GROUP BY MATURITY
        HAVING MATURITY = MAX(MATURITY);
    QUIT;

    PROC SQL NOPRINT;
        SELECT SUM(DF)
            INTO :DENO
        FROM _TEMP;
    QUIT;

    PROC DELETE DATA=_TEMP;RUN;

    %LET TP = %SYSEVALF(&YF*&NUME / &DENO);
    &TP


%MEND TP_BULLET;


%MACRO TESTER2; 
    %LET K = %TP_BULLET(ZCURVE,TAU,YF=1);
    %PUT .......&K; 
%MEND TESTER2;

%TESTER2;

我得到的错误如下

WARNING: Apparent symbolic reference DENO not resolved.
WARNING: Apparent symbolic reference NUME not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 
       1*&NUME / &DENO 

所以我认为 DATA 步骤未能创建 sas 表 _TEMP,但我不知道如何解决它。提前感谢您的任何帮助或建议

【问题讨论】:

  • 如果您想要一个函数类型的宏,请考虑查看 PROC FCMP。另外,请查看您的宏变量范围。如果在本地创建,那么一旦宏结束,宏变量就不存在了。

标签: sas sas-macro


【解决方案1】:

这不是“类似函数”的宏 - 您正在混合使用 SAS 宏语言和基本 SAS。请记住,SAS 宏语言是一种代码生成器 - 您正在生成代码,目前类似于:

%let K=data _temp; set ZCURVE; ....

请注意上面的内容不是您想要分配给宏变量 K 的内容。

为了帮助解决这个问题,请尝试使用 options mprint 运行您的宏 - 这将显示您的宏正在生成的代码。

如果你想让你的宏像一个函数一样工作,那么(至少)你应该会发现没有通过 mprint 选项生成代码..

【讨论】:

  • 正在写这个的长版本。我要补充一点:不要编写宏。您应该在 SAS 中学习的第一件事不是宏语言;它不是 SAS 的函数语言。 SAS 在数据步骤(和摘要过程)中具有非常强大的语言,您应该能够仅在几个数据步骤中完成上述所有操作。
  • RawFocus 是对的。这意味着您不能在宏中使用数据步骤,不能使用proc anything,不能使用任何会被视为代码边界的东西。你不能设置选项,有 ODS 语句,等等......即使是不使用 /* COMMENT */ 表示法的 cmets 也会被返回,并且可能会弄乱你的结果。通常,宏中的所有内容都以 % 符号或 & 符号开头。
  • 乔是对的。一般的经验法则是宏应该是最后的手段......如果你可以在不使用宏的情况下编写一些东西,那么就这样做。我不知道我是否会说“尽管不要编写宏”;-) 没有它们,自动化动态程序非常困难。
  • 感谢您的回答。这真的很有帮助。我目前面临的问题是我想创建一个大程序,使其尽可能模块化,但由于 SAS 更像是一种声明性语言,因此任务变得非常棘手。你有什么建议可以让 SAS 代码更加模块化吗?
【解决方案2】:

抛开所有哲学问题,您可以在宏中添加一个参数,指定您要创建的新宏变量 (mv)。所以不是

%Let k = %TP_BULLET(ZCURVE,TAU,YF=1);

你可以打电话

%TP_BULLET(ZCURVE,TAU,mvOutput=k,YF=1);;

你的宏需要稍微修改一下

%MACRO TP_BULLET(ZCURVE,TAU,mvOutput,YF=1);
    %GLOBAL &mvOutput;
    ........ Same code as above .........
    %Let &mvOutput = &TP; *Instead of final line with '&TP';
%MEND;

这不是一种非常符合 SAS 的方式来完成它,但如果您使用更多的编程背景而不是 SAS,它可以帮助使事情更加模块化和易于理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 2020-03-14
    相关资源
    最近更新 更多