根据特定条件使用sas表创建新变量

根据特定条件使用sas表创建新变量,sas,sas-macro,Sas,Sas Macro,我有一个SAS表,它有一个数字变量age。我需要根据age的值构造新变量。新变量应具有以下逻辑: 如果0返回值在SAS宏中没有任何特殊意义。宏被称为“生成”代码,即宏调用被文本替换,文本是在处理宏处理器“理解”的内容后留下的(基本上,涉及以&或%开头的标记(单词)) 在您的例子中,宏处理器只是扩展宏变量(其余的只是文本,宏处理器保持不变),结果是: age0=if (age=>0) and (age<=25); then return 1; else return 0; age25

我有一个SAS表,它有一个数字变量
age
。我需要根据
age
的值构造新变量。新变量应具有以下逻辑:


  • 如果0
    返回值在SAS宏中没有任何特殊意义。宏被称为“生成”代码,即宏调用被文本替换,文本是在处理宏处理器“理解”的内容后留下的(基本上,涉及以
    &
    %
    开头的标记(单词))

    在您的例子中,宏处理器只是扩展宏变量(其余的只是文本,宏处理器保持不变),结果是:

    age0=if (age=>0) and (age<=25);
    then return 1;
    else return 0;
    age25=/*and so on*/
    
    或者,使其生成一个表达式,该表达式在执行时将计算为0或1(通过将结果直接赋给变量(布尔表达式的结果为1或0),或者使用更显式):


    我同意尼古拉的观点,你应该退后一步,完全避免使用宏。您发布的示例代码似乎不正确,针对不同年龄段的四个条件仅分配给两个变量

    在SAS中,逻辑计算解析为1表示真,0表示假。此外,数字变量可以在逻辑表达式中使用,非零、非缺失值表示真或假

    因此,分配年龄范围标志变量的一系列代码如下:

    age0  =  0 < age <= 25 ;
    age25 = 25 < age <= 40 ;
    age40 = 40 < age <= 65 ;
    age65 = 65 < age <= 71 ;
    age71 = 71 < age ;
    
    取决于这个宏

    %macro make_flag_variables (var=, breakpoints=);
      %local I BREAKPOINT SUFFIX_LOW RANGE_LOW SUFFIX_HIGH RANGE_HIGH;
      %let I = 1;
      %do %while (%length(%scan(&breakpoints,&I,%str( ))));
        %let BREAKPOINT = %scan(&breakpoints,&I,%str( ));
    
        %let SUFFIX_LOW = &SUFFIX_HIGH;
        %let SUFFIX_HIGH = %sysfunc(TRANSLATE(&BREAKPOINT,_,.));
    
        %let RANGE_LOW = &RANGE_HIGH;
        %let RANGE_HIGH = &BREAKPOINT;
    
        %if &I > 1 %then %do;
            &VAR.&SUFFIX_LOW = &RANGE_LOW < &VAR <= &RANGE_HIGH; /* data step source code emitted here */
        %end; 
    
        %let I = %eval ( &I + 1 );
      %end;
    %mend;
    
    %宏生成标志变量(变量=,断点=);
    %本地I断点后缀\低范围\低后缀\高范围\高;
    %设I=1;
    %执行%while(%length(%scan(&breakpoints,&I,%str());
    %让断点=%scan(&breakpoints,&I,%str());
    %让后缀_低=&后缀_高;
    %让后缀_HIGH=%sysfunc(转换(&断点,u…);
    %让范围低=&范围高;
    %让范围_高=&断点;
    %如果&I>1%,则为%do;
    
    &变量和后缀低=&范围低<&变量是。表达式文档是一本有用的读物。“AND运算符”一节讨论了a%macro calc_age_interval(outvar, inputvar, lbound, ubound); if (&inputvar=>&lbound) and (&inputvar<=&ubound) then do; &outvar = 1; end; else do; &outvar = 0; end; %mend calc_age_interval; %calc_age_interval(outvar=age0, inputvar=age, lbound=0, ubound=25);
    %macro calc_age_interval(inputvar, lbound, ubound);
      ifn((&inputvar=>&lbound) and (&inputvar<=&ubound), 1, 0)
    %mend;
    age0 = %calc_age_interval(age, 0, 25); /* expands to age0=ifn(..., 1, 0); */
    
    if age < 0 then age_missing_or_negative = 1;
    else if age <= 25 then age0 = 1;
    else if age <= 40 then age25 = 1;
    ...
    
    age0  =  0 < age <= 25 ;
    age25 = 25 < age <= 40 ;
    age40 = 40 < age <= 65 ;
    age65 = 65 < age <= 71 ;
    age71 = 71 < age ;
    
    data have; age = 22; bmi = 20; run;
    options mprint;
    
    * easier to understand and not prone to copy paste issues or typos;
    data want;
      set have;
      %make_flag_variables (var=age, breakpoints=0 25 40 65 71)
      %make_flag_variables (var=bmi, breakpoints=0 18.5 25 30)
    run;
    
    %macro make_flag_variables (var=, breakpoints=);
      %local I BREAKPOINT SUFFIX_LOW RANGE_LOW SUFFIX_HIGH RANGE_HIGH;
      %let I = 1;
      %do %while (%length(%scan(&breakpoints,&I,%str( ))));
        %let BREAKPOINT = %scan(&breakpoints,&I,%str( ));
    
        %let SUFFIX_LOW = &SUFFIX_HIGH;
        %let SUFFIX_HIGH = %sysfunc(TRANSLATE(&BREAKPOINT,_,.));
    
        %let RANGE_LOW = &RANGE_HIGH;
        %let RANGE_HIGH = &BREAKPOINT;
    
        %if &I > 1 %then %do;
            &VAR.&SUFFIX_LOW = &RANGE_LOW < &VAR <= &RANGE_HIGH; /* data step source code emitted here */
        %end; 
    
        %let I = %eval ( &I + 1 );
      %end;
    %mend;
    
    92   data want;
    93     set have;
    94
    95     %make_flag_variables (var=age, breakpoints=0 25 40 65 71)
    MPRINT(MAKE_FLAG_VARIABLES):   age0 = 0 < age <= 25;
    MPRINT(MAKE_FLAG_VARIABLES):   age25 = 25 < age <= 40;
    MPRINT(MAKE_FLAG_VARIABLES):   age40 = 40 < age <= 65;
    MPRINT(MAKE_FLAG_VARIABLES):   age65 = 65 < age <= 71;
    96     %make_flag_variables (var=bmi, breakpoints=0 18.5 25 30)
    MPRINT(MAKE_FLAG_VARIABLES):   bmi0 = 0 < bmi <= 18.5;
    MPRINT(MAKE_FLAG_VARIABLES):   bmi18_5 = 18.5 < bmi <= 25;
    MPRINT(MAKE_FLAG_VARIABLES):   bmi25 = 25 < bmi <= 30;
    97   run;