根据特定条件使用sas表创建新变量
我有一个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
age
。我需要根据age
的值构造新变量。新变量应具有以下逻辑:
- 如果0
返回值在SAS宏中没有任何特殊意义。宏被称为“生成”代码,即宏调用被文本替换,文本是在处理宏处理器“理解”的内容后留下的(基本上,涉及以
或&
开头的标记(单词)) 在您的例子中,宏处理器只是扩展宏变量(其余的只是文本,宏处理器保持不变),结果是:%
或者,使其生成一个表达式,该表达式在执行时将计算为0或1(通过将结果直接赋给变量(布尔表达式的结果为1或0),或者使用更显式):age0=if (age=>0) and (age<=25); then return 1; else return 0; age25=/*and so on*/
我同意尼古拉的观点,你应该退后一步,完全避免使用宏。您发布的示例代码似乎不正确,针对不同年龄段的四个条件仅分配给两个变量 在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;