将*大多数*变量设置为缺失,同时保留 select 少数变量的内容

Setting *most* variables to missing, while preserving the contents of a select few

我有一个这样的数据集(但有几百个变量):

id  q1  g7  q3  b2  zz  gl  az  tre
1   1   2   1   1   1   2   1   1
2   2   3   3   2   2   2   1   1
3   1   2   3   3   2   1   3   3
4   3   1   2   2   3   2   1   1
5   2   1   2   2   1   2   3   3
6   3   1   1   2   2   1   3   3

我想保留 ID、b2 和 tre,但将其他所有设置为缺失。在这么小的数据集中,我可以轻松地使用 call missing (q1, g7, q3, zz, gl, az) - 但在具有更多变量的集合中,我更愿意说 call missing (of _ALL_ *except ID, b2, tre*)

显然,SAS 无法读懂我的想法。我考虑过涉及另一个数据步骤或 proc sql 的解决方法,我将原始变量复制到新的 ds 并将它们合并回 post,但我正在尝试找到更优雅的解决方案。

如果变量都是同一类型(数字或字符),那么您可以使用数组。

data want ;
  set have;
  array _all_ _numeric_ ;
  do over _all_;
     if upcase(vname(_all_)) not in ('ID','B2') then _all_=.;
  end;
run;

如果您不关心顺序,则只需删除变量并用 0 个观察值重新添加它们。

data want;
   set have (keep=ID B2 TRE:) have (obs=0 drop=ID B2 TRE:);
run;

另一个相当简单的选项是使用宏和基本的代码编写技术将它们设置为缺失。

例如,假设我们有一个宏:

%call_missing(var=);
  call missing(&var.);
%mend call_missing;

现在我们可以编写一个查询,使用 dictionary.columns 来识别我们想要设置为缺失的变量:

proc sql;
  select name 
    from dictionary.columns
    where libname='WORK' and memname='HAVE'
    and not (name in ('ID','B2','TRE'));  *note UPCASE for all these;
quit;

现在,我们可以结合这两个东西来得到一个包含我们想要的代码的宏变量,并使用它:

proc sql;
  select cats('%call_missing(var=',name ,')')
    into :misslist separated by ' '
    from dictionary.columns
    where libname='WORK' and memname='HAVE'
    and not (name in ('ID','B2','TRE'));  *note UPCASE for all these;
quit;

data want;
  set have;
  &misslist.;
run;

这样做的好处是它不关心变量类型,也不关心顺序。缺点是代码有点多,但应该不会特别长。

此技术使用未执行的设置语句(仅限编译时函数)来定义原始数据集中的所有变量。保持顺序和所有变量属性类型、标签、格式等。基本上将所有变量设置为缺失。将执行的下一个 SET 语句仅引入不会被设置为缺失的变量。它没有显式地将变量设置为 missing 但得到了相同的结果。

   data nomiss;
       input id  q1  g7  q3  b2  zz  gl  az  tre;
       cards;
    1   1   2   1   1   1   2   1   1
    2   2   3   3   2   2   2   1   1
    3   1   2   3   3   2   1   3   3
    4   3   1   2   2   3   2   1   1
    5   2   1   2   2   1   2   3   3
    6   3   1   1   2   2   1   3   3
    ;;;;
       run;
    proc print;
       run;
    data manymiss;
       if 0 then set nomiss;
       set nomiss(keep=id b2 tre:);
       run;
    proc print;
       run;