我想将变量的最大值重新编码为1和0(如果不是)。对于每个变量,可能会有多个具有最大值的观察值。每个值的最大值不是固定的,即每个周期的最大值可能会变化。而且有数百个变量,无法“硬编码”任何东西。
最终产品将具有与原始表相同的尺寸,即,行和列的数目等于0和1的矩阵。
这是在SAS中。我试图计算每个变量的最大值,然后将这些最大值作为新的观察值追加到数据中。然后将每个变量的列与“最大”观察值进行比较...查看以下示例无济于事:
任何见识将不胜感激。
答案 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