对于数百个变量,如何基于变量中的最大值重新编码变量的值?

时间:2019-05-01 21:27:31

标签: sas data-manipulation

我想将变量的最大值重新编码为1和0(如果不是)。对于每个变量,可能会有多个具有最大值的观察值。每个值的最大值不是固定的,即每个周期的最大值可能会变化。而且有数百个变量,无法“硬编码”任何东西。

最终产品将具有与原始表相同的尺寸,即,行和列的数目等于0和1的矩阵。

这是在SAS中。我试图计算每个变量的最大值,然后将这些最大值作为新的观察值追加到数据中。然后将每个变量的列与“最大”观察值进行比较...查看以下示例无济于事:

  1. SQL
  2. 数据步骤中的数组
  3. proc转置
  4. 格式化

任何见识将不胜感激。

2 个答案:

答案 0 :(得分:0)

以下是使用SQL完成的版本:

这个想法是我们首先计算最大值。后期选择。然后,我们将数据连接到原始数据,然后将外部连接到case-select来指定是否设置该标志。

data begin; 
  input var value; 
  cards; 
1 1
1 2
1 3
1 2.5
1 1.7
1 3
2 34
2 33
2 33
2 33.7
2 34
2 34
  ; run;


proc sql; 
create table result as
  select a.var, a.value, case when a.value = b.maximum then 1 else 0 end as is_max from 
  (select * from begin) a 
  left join 
  (select max(value) as maximum, var from begin group by var) b 
  on a.var = b.var
; 
quit;

答案 1 :(得分:0)

要避免“硬编码”,您需要使用一些代码生成。

首先让我们弄清楚您可以使用什么代码来解决问题。稍后我们将研究生成该代码的方法。

使用PROC SQL代码执行此操作可能最简单。 SAS将允许您引用变量的MAX()值。还要注意,SAS将布尔表达式的计算结果设为1(TRUE)或0(FALSE)。因此,您只想生成如下代码:

proc sql;
create table want as 
  select var1=max(var1) as var1
       , var2=max(var2) as var2
  from have
;
quit;

要生成代码,您需要源数据集中的变量列表。您可以使用PROC CONTENTS以及元数据表DICTIONARY.COLUMNS(也可以从PROC SQL外部以SASHELP.VCOLUMN访问)获得那些。

如果变量列表很小,则可以将代码生成为单个宏变量。

proc sql noprint;
select catx(' ',cats(name,'=max(',name,')'),'as',name)
  into :varlist separated by ','
  from dictionary.columns
  where libname='WORK' and memname='HAVE'
  order by varnum
;
create table want as 
  select &varlist
  from have
;
quit;

可容纳到宏变量中的最大字符数为64K。足够长,足以容纳大约2,000个变量,每个变量的名称均为8个字符。

这是使用PROC Summary和带有临时数组的数据步骤的更为复杂的方法。它确实不需要任何代码生成。

%let dsin=sashelp.class(obs=10);
%let dsout=want;
%let varlist=_numeric_;

proc summary data=&dsin nway ;
  var &varlist;
  output out=summary(drop=_type_ _freq_) max= ;
run;

data &dsout;
  if 0 then set &dsin;
  array vars &varlist;
  array max [10000] _temporary_;
  if _n_=1 then do;
    set summary ;
    do _n_=1 to dim(vars);
      max[_n_]=vars[_n_];
    end;
  end;
  set &dsin;
  do _n_=1 to dim(vars);
    vars[_n_]=vars[_n_]=max[_n_];
  end;
run;

结果:

Obs    Name       Sex    Age    Height    Weight

  1    Alfred      M      0        1         1
  2    Alice       F      0        0         0
  3    Barbara     F      0        0         0
  4    Carol       F      0        0         0
  5    Henry       M      0        0         0
  6    James       M      0        0         0
  7    Jane        F      0        0         0
  8    Janet       F      1        0         1
  9    Jeffrey     M      0        0         0
 10    John        M      0        0         0