【问题标题】:Setting *most* variables to missing, while preserving the contents of a select few将 *most* 变量设置为缺失,同时保留少数几个变量的内容
【发布时间】:2016-05-11 19:53:06
【问题描述】:

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

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,但我正在尝试找到一个更优雅的解决方案。

【问题讨论】:

  • 你关心变量是否改变顺序?
  • 不——只要它们还在那里
  • 为什么要保留失踪者?打算以后填写?如果是这样,您可能会在某个时候想要变量列表。

标签: sas datastep recode


【解决方案1】:

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

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;

【讨论】:

  • 这很有用 - 谢谢!如果不是,会更复杂吗?
  • @toandthrough 如果不是,那么您不能将它们放在一个数组中 - 您必须制作两个数组。
  • Tom,我不建议将数组命名为 _all_,这似乎会与自动变量列表 _all_ 混淆(如果 SAS 允许的话?)
  • 另外 - 可能值得注意的是,你正在做的与 OP 关于哪些变量是哪个变量的要求相反。希望显而易见,不需要太多改变,但值得指出。
  • 这是为了最大程度地保障工作安全而编写的代码。 :-) 当然,与我一起工作的大多数程序员甚至都不知道 _ALL_ 是什么。
【解决方案2】:

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

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

%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;

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

【讨论】:

    【解决方案3】:

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

       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;
    

    【讨论】:

    • 好答案。如果你解释一下它为什么工作会更好 - 我怀疑这对于很多中级程序员来说只是看代码就很难理解(至于为什么if 0 工作)。
    猜你喜欢
    • 2019-05-08
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多