如何根据 MACRO 的输出创建 SAS 变量
How do I create a SAS variable from the output of a MACRO
我有一个数据集,每个观察结果都有两个 space 分隔的列表作为字符串变量。我想要第三个变量显示字符串列表之间的重叠。使用另一个 SO post,我创建了一个宏来计算重叠。我不知道如何在数据步骤中实现它以获取第三个变量。
这是我的数据集,带有虚拟数据:
data use;
infile datalines dlm='~~';
input list1:0. list2:0. expected_match:.;
datalines;
Homer Bart~~Homer Bart~~Full
Marge Lisa~~Lisa Marge~~Full
Homer Marge~~Marge~~Partial
Bart Lisa~~Bart~~Partial
Homer Marge Bart Lisa~~Maggie~~None
;;;;
run;
这是宏,带有测试(全部通过):
%macro list_overlap(list1, list2);
%local i matches match_type;
%let matches = 0;
%do i = 1 %to %sysfunc(countw(&list1, %str( )));
%if %sysfunc(findw(&list2, %scan(&list1, &i,, s)))
%then %let matches = %eval(&matches + 1);
%end;
%if &matches = %sysfunc(countw(&list1, %str( )))
and %sysfunc(countw(&list1, %str( ))) = %sysfunc(countw(&list2, %str( )))
%then %let match_type = 'Full';
%else %if &matches = 0 %then %let match_type = 'None';
%else %let match_type = 'Partial';
match_type = &match_type%str(;)
%mend list_overlap;
%put NOTE: %list_overlap(Homer Bart,Homer Bart);
%put NOTE: %list_overlap(Marge Lisa,Lisa Marge);
%put NOTE: %list_overlap(Homer Marge,Marge);
%put NOTE: %list_overlap(Bart Lisa,Bart);
%put NOTE: %list_overlap(Homer Marge Bart List,Maggie);
这就是我尝试在数据步骤中实现它的方式:
data matches;
set use;
call execute(catt('%list_overlap(', list1, ',', list2, ')'));
run;
我在这种情况下遇到以下错误:
NOTE: Line generated by the CALL EXECUTE routine.
1 + match_type = 'Full';
__________
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
我也尝试过其他方法,但这是我最接近的方法。
我怀疑你的问题是调用 execute 没有按照你的想法去做。
发生了什么:
- 数据步骤运行,生成调用执行行
- 然后宏的东西被调用执行,你有:
代码示例:
data matches;
set use;
call execute(stuff);
run;
match_type = 'Full';
这是不合法的 - 那是一条数据步骤线,但不在数据步骤中。
与其在宏观领域完成所有这些工作,不如在数据步骤领域进行。效果一样好,随心所欲。
像这样:
%macro list_overlap(list1,list2);
matches=0;
length match_type ;
do i = 1 to countw(&list1,' ');
if findw(&list2,scan(&list1,i,' '))
then matches = matches + 1;
end;
if matches eq countw(&list1,' ') then match_type = 'Full';
else if matches eq 0 then match_type = 'None';
else match_type = 'Partial';
%mend list_overlap;
类似的东西,我现在无法测试,但通常应该可以。然后不调用execute宏,正常调用即可。
data matches;
set use;
%list_overlap(list1,list2);
run;
看起来您需要 RESOLVE() 函数而不是 CALL EXECUTE。
data matches;
set use;
match_type = resolve(cats('%list_overlap(',list1,',',list2,')'));
run;
但是根据您当前的宏定义,宏生成的所有字符 match_type = 'Full';
将包含在 MATCH_TYPE 变量的值中。因此,请删除宏当前正在生成的多余字符,以便它只生成您要保存的值。
... %then Full;
%else %if matches eq 0 %then None;
%else Partial;
我有一个数据集,每个观察结果都有两个 space 分隔的列表作为字符串变量。我想要第三个变量显示字符串列表之间的重叠。使用另一个 SO post,我创建了一个宏来计算重叠。我不知道如何在数据步骤中实现它以获取第三个变量。
这是我的数据集,带有虚拟数据:
data use;
infile datalines dlm='~~';
input list1:0. list2:0. expected_match:.;
datalines;
Homer Bart~~Homer Bart~~Full
Marge Lisa~~Lisa Marge~~Full
Homer Marge~~Marge~~Partial
Bart Lisa~~Bart~~Partial
Homer Marge Bart Lisa~~Maggie~~None
;;;;
run;
这是宏,带有测试(全部通过):
%macro list_overlap(list1, list2);
%local i matches match_type;
%let matches = 0;
%do i = 1 %to %sysfunc(countw(&list1, %str( )));
%if %sysfunc(findw(&list2, %scan(&list1, &i,, s)))
%then %let matches = %eval(&matches + 1);
%end;
%if &matches = %sysfunc(countw(&list1, %str( )))
and %sysfunc(countw(&list1, %str( ))) = %sysfunc(countw(&list2, %str( )))
%then %let match_type = 'Full';
%else %if &matches = 0 %then %let match_type = 'None';
%else %let match_type = 'Partial';
match_type = &match_type%str(;)
%mend list_overlap;
%put NOTE: %list_overlap(Homer Bart,Homer Bart);
%put NOTE: %list_overlap(Marge Lisa,Lisa Marge);
%put NOTE: %list_overlap(Homer Marge,Marge);
%put NOTE: %list_overlap(Bart Lisa,Bart);
%put NOTE: %list_overlap(Homer Marge Bart List,Maggie);
这就是我尝试在数据步骤中实现它的方式:
data matches;
set use;
call execute(catt('%list_overlap(', list1, ',', list2, ')'));
run;
我在这种情况下遇到以下错误:
NOTE: Line generated by the CALL EXECUTE routine.
1 + match_type = 'Full';
__________
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
我也尝试过其他方法,但这是我最接近的方法。
我怀疑你的问题是调用 execute 没有按照你的想法去做。
发生了什么:
- 数据步骤运行,生成调用执行行
- 然后宏的东西被调用执行,你有:
代码示例:
data matches;
set use;
call execute(stuff);
run;
match_type = 'Full';
这是不合法的 - 那是一条数据步骤线,但不在数据步骤中。
与其在宏观领域完成所有这些工作,不如在数据步骤领域进行。效果一样好,随心所欲。
像这样:
%macro list_overlap(list1,list2);
matches=0;
length match_type ;
do i = 1 to countw(&list1,' ');
if findw(&list2,scan(&list1,i,' '))
then matches = matches + 1;
end;
if matches eq countw(&list1,' ') then match_type = 'Full';
else if matches eq 0 then match_type = 'None';
else match_type = 'Partial';
%mend list_overlap;
类似的东西,我现在无法测试,但通常应该可以。然后不调用execute宏,正常调用即可。
data matches;
set use;
%list_overlap(list1,list2);
run;
看起来您需要 RESOLVE() 函数而不是 CALL EXECUTE。
data matches;
set use;
match_type = resolve(cats('%list_overlap(',list1,',',list2,')'));
run;
但是根据您当前的宏定义,宏生成的所有字符 match_type = 'Full';
将包含在 MATCH_TYPE 变量的值中。因此,请删除宏当前正在生成的多余字符,以便它只生成您要保存的值。
... %then Full;
%else %if matches eq 0 %then None;
%else Partial;