Как перекодировать значения переменной на основе значения maxmium в переменной для сотен переменных? - PullRequest
0 голосов
/ 02 мая 2019

Я хочу перекодировать максимальное значение переменной как 1 и 0, когда это не так. Для каждой переменной может быть несколько наблюдений с максимальным значением. Максимальное значение для каждого значения не является фиксированным, то есть от цикла к циклу максимальное значение для каждой переменной может изменяться. И есть сотни переменных, которые не могут ничего «жестко закодировать».

Конечный продукт будет иметь те же размеры, что и исходная таблица, то есть такое же количество строк и столбцов, что и матрица из 0 и 1.

Это внутри САС. Я попытался вычислить максимум каждой переменной, а затем добавить эти данные в качестве нового наблюдения в данные. Затем сравнение столбца каждой переменной с «максимальным» наблюдением ... просмотр следующих примеров не помог:

  1. SQL
  2. Массив в шаге данных
  3. proc transpose
  4. Форматирование

Любое понимание будет высоко ценится.

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Чтобы избежать «жесткого кода», вам нужно использовать генерацию кода.

Сначала давайте выясним, какой код вы могли бы использовать для решения проблемы.Позже мы можем изучить способы генерации этого кода.

Вероятно, это проще всего сделать с помощью кода PROC SQL.SAS позволит вам ссылаться на значение MAX () переменной.Также обратите внимание, что SAS оценивает логические выражения как 1 (ИСТИНА) или 0 (ЛОЖЬ).Итак, вы просто хотите сгенерировать код вроде:

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

Для генерации кода вам необходим список переменных в вашем исходном наборе данных.Вы можете получить их с помощью PROC CONTENTS, но также и с таблицей метаданных (представление) DICTIONARY.COLUMNS (также доступной как SASHELP.VCOLUMN из-за пределов PROC SQL).

Если список переменных небольшой, вы можете сгенерироватькод в одну макропеременную.

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;

Максимальное количество символов, которое поместится в макропеременную, составляет 64 КБ.Так долго достаточно для примерно 2000 переменных с именами по 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
0 голосов
/ 02 мая 2019

Вот версия, сделанная с использованием 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;
...