En SAS se pueden utilizar tres tipos de bucles que además pueden utilizarse en código abierto o en lenguaje macro. Los tipos de bucles son: do
, while y until
. Lo relevante es que el uso de estos bucles en código abierto o lenguaje macro es muy diferente.
Lo primero que hay que saber es que los bucles de macro solo se pueden utilizar dentro de una macro y debido al momento en que se resuelve el código hay que tener ciertas consideraciones.
código abierto |
lenguaje macro |
do x=1 to 10 by 1; [comandos] end;
|
%do x=1 %to 10 %by 1; [comandos] %end;
|
El bucle do
(y %do
) repite la ejecución de una parte de un código un número de veces que va representado por el valor de la variable indicada (x, en este caso) que comienza en 1 y termina con valor 10, saltando valores de 1 en 1. Tanto 1 como 10 se ejecutan dentro del bucle.
La diferencia entre usar el bucle do
con código abierto o lenguaje macro está en que la x que se itera, es un campo en código abierto (que saldrá en la tabla de destino) y una macrovariable en lenguaje macro. Esto afecta a la forma de uso:
código abierto |
lenguaje macro |
data salida1;
do x=1 to 10;
a=x;
output;
end;
run;
|
%macro iter_do;
data salida2;
%do x=1 %to 10;
a=&x;
output;
%end;
run;
%mend;
%iter_do;
|
Hay también limitaciones en lenguaje macro en el sentido en que no se puede incluir como condición del bucle una referencia o cálculo sobre un campo de la tabla de entrada. La razón es que el código SAS que se va a ejecutar se «escribe» en el momento de interpretar la macro, pero no se ejecuta, por lo que la referencia al contenido de la tabla no existe aún. En este caso, por ejemplo, donde se usa el campo «a» de la tabla que antes hemos creado:
%macro iter_do;
data salida2;
set salida1;
%do x=1 %to a;
a=&x;
output;
%end;
run;
%mend;
%iter_do;
Obtenemos como salida un error del tipo:
"ERROR: A character operand was found in the %EVAL function or
%IF condition where a numeric operand is required. The condition was: a".
Se puede superar este error declarando una macrovariable que tome el valor de "a" antes del inicio del bucle, pero no puede hacer referencia a un valor que no sea constante para todos los registros de la tabla. Si esto te pasa es síntoma de que tienes que estar utilizando un bucle do
, no uno %do
.
En otras ocasiones en el %to
se incluyen ciertos cálculos que no son resueltos correctamente en la declaración del bucle. Esto puede requerir declarar una macrovariable previamente o utilizar un %sysfunc()
por cada función de SAS que estemos utilizando. %sysfunc
permite utilizar la mayoría de las funciones SAS en tiempo de ejecución macro. (Existen notables excepciones como put
, que no admite %sysfunc
). Un ejemplo de esto sería:
%let inicio=22000; /* Fecha de 26mar2020 */;
%macro iter_do;
data salida3;
%do x=&inicio %to date();
a=put(&x,date9.);
output;
%end;
run;
%mend;
%iter_do;
Que daría un error como el que sigue:
ERROR: Required operator not found in expression: date()
ERROR: The %TO value of the %DO X loop is invalid.
ERROR: The macro ITER_DO will stop executing.
La solución es usar %sysfunc(date())
. Es necesario usar un %sysfunc para cada función de SAS que esté incluida en la declaración del bucle de forma que se anidarán unas dentro de otras tanto como sea necesario. Atención a los paréntesis en las estructuras más complejas.