La macro iterlist para automatizar código SAS

17 Oct

Impresionante macro de SAS que nos puede ahorrar picar mucho mucho código SAS. La macro se llama iterlist y la he encontrado en este enlace. Es código SAS muy avanzado:

%macro iterlist(code =,list =);
%*** ASSIGN EACH ITEM IN THE LIST TO AN INDEXED MACRO VARIABLE &&ITEM&I ;
%let i = 1;
%do %while (%cmpres(%scan(&list., &i.)) ne );
%let item&i. = %cmpres(%scan(&list., &i.));
%let i = %eval((&i. + 1);
%end;
%*** STORE THE COUNT OF THE NUMBER OF ITEMS IN A MACRO VARIABLE: &CNTITEM;
%let cntitem = %eval((&i. - 1);
%*** EXPRESS CODE, REPLACING TOKENS WITH ELEMENTS OF THE LIST, IN SEQUENCE;
%do i = 1 %to &cntitem.;
%let codeprp = %qsysfunc(tranwrd(&code.,?,%nrstr(&&item&i..)));
%unquote(&codeprp.)
%end;
%mend iterlist;

El funcionamiento es muy complejo, destacaría el uso de %qsysfunc. El caso es que nos permite poner listas de código. Imaginemos que tenemos que hacer la siguiente tarea:

data importes sasuser.importes;
drop i j;
array importe(10) ;
do i=1 to 20000;
do j=1 to 10;
importe(j)=ranuni(8)*1000;
end;
grupo=ranpoi(4,5);
output;
end;
run;

proc summary data=importes nway;
class grupo;
output out = agr_grupo (drop=_type_ _freq_)
mean(importe1)=media_importe1
mean(importe2)=media_importe2
...
mean(importe10)=media_importe10
sum(importe1)=suma_importe1
...
sum(importe10)=suma_importe10;
quit;

Necesitamos hacer un proc summary de 10 variables y de ellas vamos a calcular media y suma, tendremos que poner sum y mean por tantas variables como correspondan. Estamos repitiendo un código. Pues bien, esta macro nos permite repetir el código dada una lista, en este caso la lista se la pasamos como una macro:

%let lista = importe1 importe2 importe3 importe4 importe5
			importe6 importe7 importe8 importe9 importe10; 

proc summary data=importes nway;
class grupo;
output out = agr_grupo (drop=_type_ _freq_)
%iterlist(list = &lista., code = %str( mean(?)=media_? ))
%iterlist(list = &lista., code = %str( sum(?)=suma_? ));
quit;

Impresionante. Donde ponemos ? la macro pone los elementos de la lista y en el parámetro code ponemos el código que se repite con %str. A este que escribe ahora mismo se le han caído los pantalones ante semejante genialidad. Impresionante.