如何根据 MA​​CRO 的输出创建 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;