【问题标题】:How to recode values of a variable based on the maxmium value in the variable, for hundreds of variables?对于数百个变量,如何根据变量中的最大值重新编码变量的值?
【发布时间】:2019-05-01 21:27:30
【问题描述】:

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

最终产品将具有与原始表格相同的维度,即与 0 和 1 的矩阵相同的行数和列数。

这是在 SAS 中。我试图计算每个变量的最大值,然后将这些最大值作为新的观察结果附加到数据中。然后将每个变量的列与“最大”观察值进行比较......查看以下示例并没有帮助:

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

任何见解将不胜感激。

【问题讨论】:

  • 一种方法是计算 PROC MEANS 中所有变量的 MAX,输出到具有一条记录的数据集,然后将其连接到原始数据集。然后您可以使用数组将相应的原始值与 MAX 值进行比较。完成后,您可以删除所有 MAX 值列
  • 请展示您到目前为止所做的尝试。我建议首先查看 PROC STDIZE。但是 2 或 4 应该有可以工作的选项。
  • @CraigSrsen 你能解释一下如何与 MAX 值进行比较吗?我已将 MAX 附加到数据集,但不知道如何比较。
  • 您有 2 个数组 - 原始值数组 A 和列 MAXes B 的数组。'如果 A[i] = B[i] then A[i] = 1;否则 A[i] = 0;'虽然最佳做法是将 1 和 0 放在第三个数组 C 中,但不要覆盖原始数据。

标签: sas data-manipulation


【解决方案1】:

这是一个用 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;

【讨论】:

  • 您可以通过消除连接来简化。您甚至可以删除 CASE,因为 SAS 将布尔表达式计算为 0 或 1。(value=max(value)) as value
【解决方案2】:

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

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

使用 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

【讨论】:

  • 谢谢,由于其他原因,我想避免使用 SQL,但它应该在此期间工作。也简化了问题,但我认为这可能有效。本质上不是将其与 MAX 进行比较,而是将其与一些与 MAX 相关的保留代码进行比较。
  • 您可以用对这个不同问题的描述来更新问题。或者开始一个新问题。
  • 添加了一个使用 PROC Summary 和 DATA STEP 的版本。
  • 感谢@Tom,使用数组的比较是我无法弄清楚的,它非常有帮助。我想我可以根据需要将最大值换成外部规格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 2019-09-25
相关资源
最近更新 更多