我有三个由程序创建的宏列表,我正在寻找一种简单的方法来消除列表中的任何欺骗,而不会循环回创建它们的过程。
%let a=(1, 2, 3, 4);
%let b=(2, 8, 12);
%let c=(1, 3, 5, 7);
我想要的是三个消除了任何重叠值的新变量,如下所示:
%let a_mod=(4);
%let b_mod=(8, 12);
%let c_mod=(5, 7);
我知道在SAS中可能有一种相当简单的方法。有什么想法吗?感谢。
答案 0 :(得分:1)
@Joe在评论中所说的是正确的。宏变量不应该用于保存数据;这是什么数据集的用途。任何使用宏函数和逻辑直接解决问题的解决方案都可能很脆弱且容易出错。这是一种使用数据集的方法。至少在我看来,它并不完全不优雅。
在评论中,您提到可以在创建宏列表之前将值存储为数据集。太棒了!我首先假设您有三个数据集a
,b
和c
,其中包含名为v
的公共变量中的值。
首先,您要加入所有三个数据集。
proc sql;
create table abc as
select a.v as a,
b.v as b,
c.v as c
from a
full join b
on a.v = b.v
full join c
on a.v = c.v
quit;
在结果数据集中,此处称为abc
,您有a
,b
和c
列,每个列都包含同名数据集中的值。由于数据集已完全连接,因此存在所有值。然后,在任何给定的行中,如果a
,b
和c
中只有一个不丢失,则表示您没有重复。
现在,您可以将值分开,省略重复项,类似于您的a_mod
等宏列表。
data a_mod(keep=a) b_mod(keep=b) c_mod(keep=c);
set abc;
if n(a, b, c) = 1 then do;
if a ne . then output a_mod;
else if b ne . then output b_mod;
else if c ne . then output c_mod;
end;
run;
n()
函数计算非缺失参数的数量。
现在,如果您需要列表再次使用最终用途,您可以使用into:
中的proc sql
子句重新创建它们,例如:
proc sql noprint;
select a
into: a_mod
from a_mod
separated by ', ';
quit;
%let a_mod = (&a_mod); /* To get the surrounding parentheses back */
虽然这会在您的问题中仅提供一些列表,但这样可以满足您的需求,但请注意,如果您有一个简单的方法,例如此方法会变得很丑陋和/或烦人很多名单。