Macros SAS宏未遍历整个数据集
我对SAS非常陌生,并尝试学习做事情的最佳实践。我试着编写一个简单的宏来挑选特定数据集中缺少值的任何给定字段。其思想是遍历每个记录(行),让do(for)循环充当if语句中的OR。我的问题是Macros SAS宏未遍历整个数据集,macros,sas,Macros,Sas,我对SAS非常陌生,并尝试学习做事情的最佳实践。我试着编写一个简单的宏来挑选特定数据集中缺少值的任何给定字段。其思想是遍历每个记录(行),让do(for)循环充当if语句中的OR。我的问题是 我的理解是,一旦调用宏,就应该对数据集中的每一行执行一次,但在这种情况下,它似乎只执行一次(也就是说,do循环似乎只执行一次,而不是100次) 有没有更好的办法 /* say I have a dataset with fieldA fieldB fieldC fieldD etc. and 100 rec
/* say I have a dataset with fieldA fieldB fieldC fieldD etc. and 100 records, some of which were missing */
%let varList = fieldA fieldB; /* check fieldA and fieldB */
%ReportIncompleteFields(sasdata.myDAta, &varList., work.tempData);
%macro ReportIncompleteFields(inDataName, chkVars, outDataName);
%let numVars = %sysfunc(countw(&chkVars.));
length keepRrd 8;
keepRcd = 0;
data &outDataName.;
set &inDataName.;
%do ii = 1 %to &numVars.;
%let iiVarName = %scan(&chkVars., &ii.);
%if &iiVarName. = '' %then keepRcd=keepRcd+1;
%end;
%if keepRcd=0 %then delete;
run;
%mend ReportIncompleteFields;
SAS数据步骤作为一个循环,在这里您根本不需要宏逻辑,最多需要一个数组。查找nmiss/cmiss或缺少的()函数。关键是要确保变量都是相同的类型,或者声明两个数组,一个用于数字,一个用于字符数据。这假设所有变量都具有相同的类型。如果该假设不成立,则创建两个参数,一个用于列出字符,一个用于变量,另一个用于数值并扩展逻辑
%macro ReportIncompleteFields(inDataName, chkVars, outDataName);
data &outDataName.;
set &inDataName.;
array check(*) &chkVars;
if nmiss(of check(*))=0;*keep all variables with no records missing;
run;
%mend ReportIncompleteFields;
我不确定这是为了什么,但是SAS也会自动从大多数统计过程中排除按大小写丢失的数据,或者在默认情况下需要它的位置,所以您可能不需要它。SAS数据步骤充当一个循环,您在这里根本不需要宏逻辑,最多只需要一个数组。查找nmiss/cmiss或缺少的()函数。关键是要确保变量都是相同的类型,或者声明两个数组,一个用于数字,一个用于字符数据。这假设所有变量都具有相同的类型。如果该假设不成立,则创建两个参数,一个用于列出字符,一个用于变量,另一个用于数值并扩展逻辑
%macro ReportIncompleteFields(inDataName, chkVars, outDataName);
data &outDataName.;
set &inDataName.;
array check(*) &chkVars;
if nmiss(of check(*))=0;*keep all variables with no records missing;
run;
%mend ReportIncompleteFields;
我不确定这是为了什么,但是SAS也会自动从大多数统计过程中排除按大小写丢失的数据,或者在默认情况下需要它的位置,所以您可能不需要它。SAS数据步骤充当一个循环,您在这里根本不需要宏逻辑,最多只需要一个数组。查找nmiss/cmiss或缺少的()函数。关键是要确保变量都是相同的类型,或者声明两个数组,一个用于数字,一个用于字符数据。这假设所有变量都具有相同的类型。如果该假设不成立,则创建两个参数,一个用于列出字符,一个用于变量,另一个用于数值并扩展逻辑
%macro ReportIncompleteFields(inDataName, chkVars, outDataName);
data &outDataName.;
set &inDataName.;
array check(*) &chkVars;
if nmiss(of check(*))=0;*keep all variables with no records missing;
run;
%mend ReportIncompleteFields;
我不确定这是为了什么,但是SAS也会自动从大多数统计过程中排除按大小写丢失的数据,或者在默认情况下需要它的位置,所以您可能不需要它。SAS数据步骤充当一个循环,您在这里根本不需要宏逻辑,最多只需要一个数组。查找nmiss/cmiss或缺少的()函数。关键是要确保变量都是相同的类型,或者声明两个数组,一个用于数字,一个用于字符数据。这假设所有变量都具有相同的类型。如果该假设不成立,则创建两个参数,一个用于列出字符,一个用于变量,另一个用于数值并扩展逻辑
%macro ReportIncompleteFields(inDataName, chkVars, outDataName);
data &outDataName.;
set &inDataName.;
array check(*) &chkVars;
if nmiss(of check(*))=0;*keep all variables with no records missing;
run;
%mend ReportIncompleteFields;
我不确定这是为了什么,但是SAS也会自动从大多数统计过程中排除按大小写丢失的数据,或者在默认情况下需要这些数据的地方,因此您可能不需要这些数据。这里的问题是不理解宏代码的作用。宏代码最常见的用途是生成SAS代码。宏逻辑不会生成任何SAS代码 考虑您的第一块宏代码:
%do ii = 1 %to &numVars.;
%let iiVarName = %scan(&chkVars., &ii.);
%if &iiVarName. = '' %then keepRcd=keepRcd+1;
%end;
值&iiVarName将是宏变量CHKVARS中列出的一个变量的名称。也就是说,它将是一个类似FieldA的字符串。该字符串永远不会等于相邻的两个单引号。因此%THEN子句永远不会生成任何代码。即使您确实将'
作为CHKVARS中的变量名之一传入,将生成的代码也缺少表示赋值语句结束的分号。数字1后的分号将标记%IF语句的结尾
第二个%IF语句,%IF keepRcd=0%,则删除
也可能永远不会为真,因为字母流keepRcd
永远不等于数字0
因此,如果您的目标是只保留不缺少所列字段的记录,那么只需使用CMISS()函数。例如,该程序将输入数据集分为好数据集和坏数据集
data good bad ;
set have ;
if 0=cmiss(of fieldA fieldB) then output good;
else output bad;
run;
将其包装到宏中非常简单,可能是浪费时间。这里的问题是不理解宏代码的作用。宏代码最常见的用途是生成SAS代码。宏逻辑不会生成任何SAS代码 考虑您的第一块宏代码:
%do ii = 1 %to &numVars.;
%let iiVarName = %scan(&chkVars., &ii.);
%if &iiVarName. = '' %then keepRcd=keepRcd+1;
%end;
值&iiVarName将是宏变量CHKVARS中列出的一个变量的名称。也就是说,它将是一个类似FieldA的字符串。该字符串永远不会等于相邻的两个单引号。因此%THEN子句永远不会生成任何代码。即使您确实将'
作为CHKVARS中的变量名之一传入,将生成的代码也缺少表示赋值语句结束的分号。数字1后的分号将标记%IF语句的结尾
第二个%IF语句,%IF keepRcd=0%,则删除
也可能永远不会为真,因为字母流keepRcd
永远不等于数字0
因此,如果您的目标是只保留不缺少所列字段的记录,那么只需使用CMISS()函数。例如,该程序将输入数据集分为好数据集和坏数据集
data good bad ;
set have ;
if 0=cmiss(of fieldA fieldB) then output good;
else output bad;
run;
将其包装到宏中非常简单,可能是浪费时间。这里的问题是不理解宏代码的作用。宏代码最常见的用途是生成SAS代码。宏逻辑不会生成任何SAS代码 缺点