Возможно, вам придется переосмыслить то, о чем вы можете думать.Есть пары парных размерных пересечений 2*10 + 2*24 + 10*24 = 308
, для которых вы хотите получить максимумы.Макрос, безусловно, является лучшим способом кодирования максимального определения в шаге DATA.Ручное кодирование решения очень склонно к копированию ошибок вставки и общего выпадения волос.
Гораздо лучшим процедурным способом было бы транспонировать все махинации в вектор, категоричный по пространственному имени и позволяющийProc MEANS
, SUMMARY
или UNIVARIATE
вычисляют максимумы для парных пересечений, как было бы сделано с оператором WAYS 2
.
В примерах кода показаны оба подхода и выполняется Proc COMPARE … OUT= OUTNOEQUAL
дляПокажите, что результирующее вычисление максимума для каждого размерного пересечения является идентичным.(Т.е. данные OUT=
не имеют строк, что означает, что все переменные с одинаковыми именами имеют абсолютно одинаковые значения)
Некоторые данные с несколькими экземплярами массива 3 измерений (1 строка на экземпляр)
%macro make_data (
out=have,
dim1=x, count1=2,
dim2=y, count2=10,
dim3=z, count3=24
);
%local index1 index2;
data have;
length rownum 8;
array cells(&count1,&count2,&count3)
%do index1 = 1 %to &count1;
%do index2 = 1 %to &count2;
&dim1.&index1._&dim2.&index2._&dim3.1 - &dim1.&index1._&dim2.&index2._&dim3.&count3
%end;
%end;
(1:%eval(&count1*&count2*&count3));
rownum = 1;
output;
do rownum = rownum+1 to 10;
array cells_flat x:;
do _n_ = 1 to dim(cells_flat);
cells_flat(_n_) = cells_flat(_n_) + dim(cells_flat);
end;
output;
end;
drop _:;
run;
%mend;
options mprint;
%make_data();
Макрос кодирует формулу MAX () для каждого пересечения
%macro every_which_way (
data=have,
out=want,
dim1=x, count1=2,
dim2=y, count2=10,
dim3=z, count3=24
);
data &out;
set &data;
%local index1 index2 item1 item2 item3 crossing;
%local map1 map2 map3;
%local map&dim1. ; %let map&dim1. = 1;
%local map&dim2. ; %let map&dim2. = 2;
%local map&dim3. ; %let map&dim3. = 3;
/*
array cells(&count1,&count2,&count3)
%do index1 = 1 %to &count1;
%do index2 = 1 %to &count2;
&dim1.&index1._&dim2.&index2._&dim3.1 - &dim1.&index1._&dim2.&index2._&dim3.&count3
%end;
%end;
;
*/
%* item 1 & 2 are dimensions, for pairwise crossing;
%do item1 = 1 %to 2;
%let map1 = &&&&map&&dim&item1;
%do item2 = %eval(&item1+1) %to 3;
%let map2 = &&&&map&&dim&item2;
%* item3 is dimension being measured for max;
%let item3 = %eval (1 + 2 + 3 - &item1 - &item2);
%let map3 = &&&&map&&dim&item3;
%* for each level of the crossed dimensions;
%do index1 = 1 %to &&count&item1..;
%do index2 = 1 %to &&count&item2..;
%let crossing = &&dim&item1..&index1._&&dim&item2..&index2.;
%* data set variable MAX_OVER_<item1-dimension><item1-index>_<item2-dimension><item2-index>;
max_over_&crossing. = MAX ( .
%do index3 = 1 %to &&count&item3..;
%local addr1 addr2 addr3;
%let addr&map1 = &&dim&item1..&index1.;
%let addr&map2 = &&dim&item2..&index2.;
%let addr&map3 = &&dim&item3..&index3.;
, &addr1._&addr2._&addr3.
%end;
);
%end;
%end;
%end;
%end;
run;
%mend;
%every_which_way();
Proc MEANS вычисление каждого пересечения после транспозиционного преобразования
proc transpose data=have out=have_vector;
by rownum;
run;
data have_vector_view / view=have_vector_view;
set have_vector;
dim1 = scan (_name_,1,'_');
dim2 = scan (_name_,2,'_');
dim3 = scan (_name_,3,'_');
run;
proc means noprint data=have_vector_view;
by rownum;
class dim1 dim2 dim3;
ways 2;
var col1;
output out=want_max max=max;
run;
data want_max_prepivot_view / view=want_max_prepivot_view;
set want_max;
_name_ = catx('_', of dim:);
run;
proc transpose data=want_max_prepivot_view out=want_max_wide(drop=_name_) prefix=max_over_;
by rownum;
id _name_;
var max;
run;
И сравнение методов
proc compare noprint base=want compare=want_max_wide out=differences outnoequal;
by rownum;
run;