我正在使用一个SAS宏,它使用sql来构建CODELIST,然后在数据中添加一个标志。因此格式表包含ICD代码和一些变量标志名称。所以这个宏基本上只是如果我输入一个flagName它会在mydata中创建一个标志变量。
%MACRO flag(flagName);
PROC SQL;
SELECT QUOTE(ICD) INTO :CODELIST SEPARATED BY ","
FROM Format_Table
WHERE FLAG = %unquote(%str(%')&flagName%str(%'));
QUIT;
DATA mydata; SET mydata;
IF DIAG IN (&CODELIST) THEN &flagName = 1;
RUN;
%MEND flag;
但是当我有太多的flagNames时,它将无法正常工作,这意味着我必须逐个输入每个变量名称。而falgNames是所有的疾病名称,如乳房,前列腺等。我想知道是否有一种方法可以创建一个具有变量名称的数组,并每次运行宏与数组值而不是列出所有的宏命令。 像:
Array variables [I] breast prostate lung;
%DO I = 1 to DIM(variables);
%macro(inputVarialeName = variables[I]);
END;
如果有办法,请帮助我。非常感谢您的帮助。
答案 0 :(得分:0)
使用CALL EXECUTE,文档中有一个完整的示例here。
首先,你需要以某种方式创建一个变量列表,要么输入它,要么从SASHELP.VCOLUMN或PROC CONTENTS中提取它。
/********************************************************************
Example : Call macro using parameters from data set
********************************************************************/
proc sort data=sashelp.class out=class;
by age sex;
run;
%macro summary(age=, sex=);
proc print data=sashelp.class;
where age=&age and sex="&sex";
run;
%mend;
data sample;
set class;
by age sex;
if last.sex;
string =
catt('%summary(age=', age, ',sex=', sex, ');');
put string;
run;
data _null_;
set sample;
call execute(string);
run;
答案 1 :(得分:0)
您可以创建第二个循环输入的宏,并为每个项调用另一个宏。
你应该真正发布工作代码,%macro (inputVarialeName = v1);
有点不敏感 - 你定义或调用吗? %my_macro (inputVarialeName = v1);
在调用方面会更加明确。
假设您有一个需要多次调用的宏
%macro my_macro (var=);
/* generate some data step code that does something with &var, lets log it */
putlog 'NOTE: ' &var=;
%mend;
或者宏可能是某些将片段转换为百分比的SQL片段
%macro my_macro (var=);
, &var * 100 as &var._pct
%mend;
或是Proc REPORT
%macro my_macro (var=);
define &var / center;
%mend;
创建第二个宏,它接受一个空格分隔的变量列表,就像程序中的VAR
语句一样。
%macro do_my_macro_for_each (vars=);
%local index token;
%let index = 1;
%do %while (1);
%let token = %scan(&vars, &index);
%if %length(&token) = 0 %then %return;
/* invoke my macro using i-th token */
%my_macro (var=&token)
%let index = %eval (&index + 1);
%end;
%mend;
然后调用' do-er'使用您的变量列表
data have;
array v(1000) (1:1000);
run;
data _null_;
set have;
%do_my_macro_for_each (vars=v1 v32 v185 v237);
run;
----- LOG -----
NOTE: v1=1
NOTE: v32=32
NOTE: v185=185
NOTE: v237=237
NOTE: There were 1 observations read from the data set WORK.HAVE.
可以通过互联网搜索或SAS conference paper searches(lexjansen.com)找到实施SAS宏代码的其他讨论,这些代码可以执行通用的每个处理。
答案 2 :(得分:0)
Qimeng有一个ICD分类表,用于设置状态标志。
data DX_CLASSES;
length ICD $5 flag $32;
input
ICD & Flag ; datalines; /* NOTE: & requires data values be separated by 2 or more spaces */
1 xxx
23.1 xxx
2 yyy
2.1 yyy
3.3 yyy
run;
并且有一些患者诊断信息
data DIAGNOSES;
length pat_id visit_id diagnosis $5;
input
pat_id & visit_id & diagnosis & record_id; datalines;
1 1 23.1 1
1 1 2 2
1 1 77.7 3
1 2 23.1 4
2 1 2.1 5
run;
并希望每个不同的标志值添加一列。 将“标志”这个短语视为“医疗概念”
是合适的 pat_id visit_id diagnosis record_id xxx yyy
------ -------- --------- --------- --- ---
1 1 23.1 1 1 0
1 1 2 2 0 1
1 1 77.7 3 0 0
1 2 23.1 4 1 0
2 1 2.1 5 0 1
单个SQL可以为每个不同的应用分类查找。此纯SQL语句可用作开发重复调用的适当宏的基础。 EXISTS
条件可用作高效IN
查找评估。
proc sql;
create table want as
select have.*
, exists (select * from DX_CLASSES where DX_CLASSES.flag = "xxx" and DX_CLASSES.ICD = have.DIAGNOSIS) as xxx
, exists (select * from DX_CLASSES where DX_CLASSES.flag = "yyy" and DX_CLASSES.ICD = have.DIAGNOSIS) as yyy
from DIAGNOSES as have
;
假设流程
%macro do'ee
emits something specific to one flag
%mend
%macro do'er
do for each item in flags
invoke do'ee
end
%mend;
proc sql;
create ... as
select ...
%do'er ( list of flags )
from ...
;
'do-er'调用可能是
%apply_concepts (data=DIAGNOSES, concepts=DX_CLASS, flag=xxx yyy);
'do-er'实现中的'do-ee'(flag =中的每个项目)调用可能是
%binary_flag_concept(outer=have, inner=&concepts, flag=&flag_item)
'do-ee'实现会发出一个exist
子句
, exists (
select *
from &concepts as inner
where inner.flag = "&flag"
and inner.ICD = have.DIAGNOSIS
) as &flag
最外面的代码可能是
proc sql;
create table want as
select have.*
%apply_concepts (data=DIAGNOSES, concepts=DX_CLASS, flag=xxx yyy)
from DIAGNOSES as have
;
我的第一个答案中的信息应该指导你编写do'er并且它是do'ee。尝试后,如果您有任何问题,请创建一个新问题。
注意:SAS有许多其他方法可以将分类查找和应用程序作为新列执行。其中包括格式,合并和哈希对象。并且每种方式也可以利用'do-er'和'do-ee'流程。最重要的是在开始宏观化之旅之前理解数据处理的简单代码版本。
答案 3 :(得分:0)
由于您已经拥有一个宏,因此最简单的方法是将宏更改为一次支持多个标志。您可以保持逻辑相同,只需添加一些宏循环。
%macro flag(flaglist);
%local flagname i n &flaglist;
%let n=%sysfunc(countw(&flaglist));
proc sql noprint;
%do i=1 %to &n ;
%let flagname=%scan(&flaglist,&i);
%let &flagname='Not Found';
select quote(trim(icd)) into :&flagname separated by ','
from format_table
where flag = "&flagname"
;
%end;
quit;
data mydata;
set mydata;
%do i=1 %to &n ;
%let flagname=%scan(&flaglist,&i);
&flagname = diag in (&&&flagname);
%end;
run;
%mend flag;