【问题标题】:Setting Macro Variable equal to value in table设置宏变量等于表中的值
【发布时间】:2015-04-15 16:41:59
【问题描述】:

我有一张单行四列的表格。我想创建 4 个以每列命名的宏变量,其中值设置为 1 行中的值。

如果这是 R,我可以通过以下方式直接访问这些值:

newvar1=tablename[1,1]
newvar2=tablename[1,2]...

我是否可以从表中选择值并将宏变量设置为等于该值?

比如:

%macrovar1=tablename[1,1]...

除了等号右边明显是R代码而不是SAS。

谢谢

【问题讨论】:

    标签: sas


    【解决方案1】:

    你可以像这样使用 proc sql 来做:

    proc sql noprint inobs=1;
      select name into :my_val from sashelp.class;
    quit;
    %put &my_val;
    

    或者您可以像这样使用数据步骤中的call symput

    data _null_;
      set sashelp.class(obs=1);
      call symput('my_val',name);
    run;
    

    为了更灵活,我们使用了一个实用宏,它允许我们从代码中的任何位置检查值。我已对其稍作修改以适应您的要求,但用法如下:

    %let my_val = %get_val(iDs=sashelp.class, iField=name);
    

    您也可以在 proc 或 datastep 中间使用它,如下所示:

    data _null_;
      my_value = "%get_val(iDs=sashelp.class, iField=name)";
    run;
    

    甚至:

    proc sql noprint;
      create table want as
      select * from sashelp.class
      where name = "%get_val(iDs=sashelp.class, iField=name)"
      ;
    quit;
    

    这里是宏定义:

    %macro get_val(iDs=, iField=);
      %local dsid pos rc result cnt value;
    
      %let result=;
      %let cnt=0;
    
      /*
      ** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
      */
      %if "&iDs" ne "" and "&iField" ne "" %then %do;
    
        %let dsid=%sysfunc(open(&iDs,i));
        %if &dsid %then %do;
    
          %let pos=%sysfunc(varnum(&dsid,&iField));
          %if &pos %then %do;
    
            %let rc=%sysfunc(fetch(&dsid));
    
            %if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
              %let value = %qsysfunc(getvarc(&dsid,&pos));
              %if "%trim(&value)" ne "" %then %do;
                %let value = %qtrim(&value);
              %end;
            %end;
            %else %do;
              %let value = %sysfunc(getvarn(&dsid,&pos));
            %end;
            &value
    
          %end;
          %else %do;
            %put ERROR: MACRO.GET_VAL.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
          %end;
        %end;
        %else %do;
          %put ERROR: MACRO.GET_VAL.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
        %end;
    
        %let rc=%sysfunc(close(&dsid));
    
      %end;
      %else %do;
        %put ERROR: MACRO.GET_VAL.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
      %end;
    
    %mend;
    

    上述宏是在here 找到的%ds2list 宏的缩略版。

    【讨论】:

    • 我只是要补充一点,我在上述方法中的首选方法是使用%let = 方法,因为这既更简洁,也更清晰(即它是清楚的是所有代码所做的只是为宏变量设置一个值,这对于data 步骤或proc sql 语句来说并不那么清楚)。这就是我添加第三种宏方法的原因。然而,大多数人满足于数据步骤或 proc sql。
    【解决方案2】:

    有几种方法,但最简单的是:

    data _null_;
      set have;
      if _n_=1 then do;
        call symputx('macrovar1',var1);
       *more of these;
      end;
      stop;
    run;
    

    这会打开数据集,然后如果在第一行(_n_ 是数据步循环的迭代,在大多数情况下是第一行),则使用 call symputx 将其值分配给宏变量。

    我要注意的是,您应该记住,SAS 宏变量不是数据变量,没有数据类型(始终是文本),并且 通常 不用于以您想要的方式存储数据在 R 中使用向量。

    【讨论】:

    • 我认为这是正确的想法,但它并没有达到我想要的效果。例如,假设我的一列名为 first name,而这一行中的值是 Jim。我想创建一个像“%fname=Jim”这样的宏变量,这样我以后可以在程序中设置变量等于&fname,并得到Jim。它现在所做的是附加没有值的 fname 列。所以如果我写“data something;set table; var=&fname;run;”我得到一个名为 Jim 的新列,没有值,而不是 var=Jim。
    • @Carl 听起来您可能正试图在您为其分配值的同一数据步中使用宏变量值。这是正确的吗?您能否通过一个特定示例创建一个新问题,显示代码未按预期运行?
    • 您想要 Jim 的值,还是名为 Jim 的变量?如果你想要 Jim 的值,它是 var="&fname.";,因为它是文本。就像我说的 - 这不是一个向量,就像在r 中一样。这是文本,就像您手动输入的一样。可能性很好,有比使用宏变量更好的方法来做到这一点,具体取决于您在做什么。
    • 我让它工作了。我有一些导致问题的单独错误。谢谢大家
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    相关资源
    最近更新 更多