tutorial macro ejemplos definicion data _null_ sas sas-macro

sas - ejemplos - La variable de macro tiene un valor diferente dentro de DATA Step. ¿Por qué?



macro variables ejemplos (3)

Tenía razones para procesar diferentes variables de un conjunto de datos determinado mediante un proceso repetitivo. Para resolver este problema, escribí una macro cuya entrada sería la variable particular de interés. La macro luego procesaría solo esa variable. Sin embargo, resultó que una de las variables debía manejarse de forma ligeramente diferente. Mi solución rápida fue aplicar un condicional; si la variable fue la excepción, realice una acción diferente de las otras variables. Problema resuelto, ¿verdad? No.

Encuentro que el valor de la variable macro cambia dependiendo de si se usa o no dentro de un paso de datos.

Por favor considera,

data example; length dataset_var1 $ 6 dataset_var2 $ 6; input dataset_var1 $ dataset_var2; datalines; value1 value2 value3 value4 ; run;

La macro y su llamada:

%macro NoQuotes(macro_var); %put &macro_var. ; data _null; set example; put &macro_var. ; if &macro_var. = ''dataset_var1'' then do; put "The IF evaluated"; end; else do; put "The ELSE evaluated"; end; run; %put &macro_var. ; %mend; %NoQuotes(dataset_var1);

Esto produce la siguiente entrada de registro:

dataset_var1 value1 The ELSE evaluated value3 The ELSE evaluated NOTE: There were 2 observations read from the data set WORK.EXAMPLE. NOTE: The data set WORK._NULL has 2 observations and 2 variables. NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.00 seconds dataset_var1

Observe cómo el valor de macro_var cambia dependiendo de si está dentro del paso DATA. Cuando se encuentra dentro del paso DATA, macro_var toma los valores de dataset_var1 , es decir, value1 y value3 , en lugar de conservar el nombre dataset_var1 como era de esperar. Una vez fuera del paso DATA, el valor de macro_var vuelve mágicamente a su valor correcto.

A sugerencia de un compañero de trabajo, puse el nombre de la macrovariable entre comillas dentro de la declaración condicional. Esto hace que el comportamiento condicional se comporte como se esperaba.

%macro WithQuotes(macro_var); %put &macro_var. ; data _null_; set example; put &macro_var. ; if "&macro_var." = ''dataset_var1'' then do; put "The IF evaluated"; end; else do; put "The ELSE evaluated"; end; run; %put &macro_var. ; %mend; %WithQuotes(dataset_var1);

Esto produce la siguiente entrada de registro:

dataset_var1 value1 The IF evaluated value3 The IF evaluated NOTE: There were 2 observations read from the data set WORK.EXAMPLE. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds dataset_var1

Aunque el condicional ahora se ejecuta como se esperaba, vemos nuevamente que la variable macro toma los valores de value1 y value3 .

El comportamiento de las variables macro parece ir en contra de todo lo que he conocido sobre el concepto de variables de BASIC, C ++, Java, C #, VBA, Python, Lisp y R.

¿Puede alguien por favor explicarme qué está pasando? He leído la mayoría de la Referencia del lenguaje de macros , pero no estoy seguro de dónde encontrar la explicación de este comportamiento.


la variable macro toma los valores de value1 y value3

No: la variable macro es una cadena de caracteres dataset_var1 . La variable macro no cambia. La variable macro no es lo mismo que la variable con el mismo nombre dentro del paso de datos. Cada vez que el macroprocesador SAS ve &dataset_var1 lo reemplaza con la cadena de caracteres dataset_var1 . El macroprocesador SAS está generando código por sustitución de cadena, no evaluando el código.

Consejo: si options mprint; puedes ver el código que genera el macroprocesador.

%put &macro_var; reemplaza &macro_var con la cadena dataset_var1 y coloca la cadena dataset_var1 en el registro, como si hubiera escrito %put dataset_var1;

ĪEn el paso de datos, el macroprocesador vuelve a redactar las siguientes declaraciones:

put &macro_var ; se convierte en put dataset_var1;

put (no %put ), escribe el valor de una variable de conjunto de datos en el registro, por lo que pone el valor de la variable dataset_var1 en el registro. Esta variable es ''value1'' o ''value3''.

if "&macro_var." = ''dataset_var1'' if "&macro_var." = ''dataset_var1'' convierte if dataset_var1 = ''dataset_var1'' No está comparando &macro_var a ''dataset_var1`, está comparando'' value1 ''='' dataset_var1 ''para la primera fila, y'' value3 ''='' dataset_var1 ''. Esto es falso para ambas filas.

El %put &macro_var; final %put &macro_var; es el mismo que el primero, ya que &macro_var no ha cambiado.

El comportamiento de las variables macro parece ir en contra de todo lo que he conocido sobre el concepto de variables de BASIC, C ++, Java, C #, VBA, Python, Lisp y R.

¡Eso es porque las variables macro SAS no son variables SAS! Las macros SAS se parecen más a las declaraciones del preprocesador C , no al código C. Las variables macro SAS son como las directivas #define compilador. En mi experiencia, son una de las causas más comunes de confusión y errores en los programas de SAS, y deben eliminarse siempre que sea posible.


El lenguaje macro genera código. En términos simples, reemplaza el texto.

Entonces, su primera llamada a macro crea el siguiente código

%put dataset_var1 ; data _null; set example; put dataset_var1 ; if dataset_var1 = ''dataset_var1'' then do; put "The IF evaluated"; end; else do; put "The ELSE evaluated"; end; run; %put dataset_var1 ;

Debido a que la variable existe en el conjunto de datos, hace referencia al valor de la variable y el resultado que está viendo es el que yo esperaría.

Cuando agrega comillas, ya no está haciendo referencia a la variable, está creando una cadena de texto que coincidirá con el valor en su condición IF.

Esta es una comparación de cadena a cadena:

if "dataset_var1" = ''dataset_var1'' then do;

Esto hace referencia a una variable dataset_var1, que contiene dos valores, valor1 / valor3.

if dataset_var1 = ''dataset_var1'' then do;

Si usa OPTIONS MPRINT SYMBOLGEN; Verá en qué SAS está resolviendo las variables en cada paso y cómo está evaluando la lógica.


Respuesta corta: intente utilizar la instrucción de macro% IF en lugar del enunciado de IF del lenguaje de paso de datos.

Respuesta larga: el lenguaje de macros es un preprocesador que procesa texto para generar código. En general, el lenguaje de macro no conoce los conjuntos de datos SAS o las variables en los conjuntos de datos. El lenguaje de paso DATA procesa conjuntos de datos y variables del conjunto de datos. El lenguaje de macros tiene un aspecto similar al del paso de datos, pero tienen propósitos completamente diferentes y son dos idiomas diferentes.

Considerar:

87 options mprint; 88 89 %macro ShowValue(var); 90 data _null_; 91 set sashelp.class (obs=3); 92 93 %put The macro variable VAR has the value: &VAR; 94 put "The dataset variable &VAR has the value: " &VAR; 95 96 run; 97 98 %mend; 99 100 %ShowValue(var=height) MPRINT(SHOWVALUE): data _null_; MPRINT(SHOWVALUE): set sashelp.class (obs=3); The macro variable VAR has the value: height MPRINT(SHOWVALUE): put "The dataset variable height has the value: " height; MPRINT(SHOWVALUE): run; The dataset variable height has the value: 69 The dataset variable height has the value: 56.5 The dataset variable height has the value: 65.3 NOTE: There were 3 observations read from the data set SASHELP.CLASS.

El lenguaje de macro tiene una instrucción% PUT, el lenguaje de paso de datos tiene una instrucción PUT. Arriba, el propósito de la instrucción% PUT es mostrar el valor de la variable de macro (parámetro) denominada VAR . El usuario le ha pasado un valor de height . El propósito de la declaración PUT anterior es mostrar el valor de la variable de paso de datos que el usuario ha nombrado. Debido a que el usuario ha pasado la height del valor, se enumera el valor de esa variable del conjunto de datos (para los tres registros que se procesan). La variable macro llamada VAR siempre tiene el valor height . La variable del conjunto de datos denominada height tiene diferentes valores para diferentes registros. Tenga en cuenta que la instrucción% PUT solo se ejecuta una vez, incluso si está dentro del ciclo de paso de datos. Esto se debe a que las sentencias de macro se ejecutan antes de ejecutar cualquier código de paso de datos (o incluso compilarlo). La instrucción PUT es un código de paso de datos, por lo que se compila y ejecuta una vez por cada registro procesado por el paso de datos. Las instrucciones PUT necesitan una cita para poder distinguir la literal del texto del nombre de la variable de paso de datos. La instrucción% PUT (y de hecho todo el lenguaje de macros) no necesita comillas porque las variables macro están referenciadas por &.

Si desea realizar una evaluación condicional basada en el valor de una variable de macro para decidir qué paso de datos debe generar la macro, puede usar una instrucción de macro% IF, por ejemplo:

102 %macro ShowValue(var); 103 data _null_; 104 set sashelp.class (obs=3); 105 106 %if &var=height %then %do; 107 &var=&var * 2.54; *convert height from inches to cm; 108 %end; 109 110 %put The macro variable VAR has the value: &VAR; 111 put "The dataset variable &VAR has the value: " &VAR; 112 113 run; 114 115 %mend; 116 117 %ShowValue(var=height) MPRINT(SHOWVALUE): data _null_; MPRINT(SHOWVALUE): set sashelp.class (obs=3); MPRINT(SHOWVALUE): height=height * 2.54; MPRINT(SHOWVALUE): *convert height from inches to cm; The macro variable VAR has the value: height MPRINT(SHOWVALUE): put "The dataset variable height has the value: " height; MPRINT(SHOWVALUE): run; The dataset variable height has the value: 175.26 The dataset variable height has the value: 143.51 The dataset variable height has the value: 165.862 NOTE: There were 3 observations read from the data set SASHELP.CLASS. 118 %ShowValue(var=weight) MPRINT(SHOWVALUE): data _null_; MPRINT(SHOWVALUE): set sashelp.class (obs=3); The macro variable VAR has the value: weight MPRINT(SHOWVALUE): put "The dataset variable weight has the value: " weight; MPRINT(SHOWVALUE): run; The dataset variable weight has the value: 112.5 The dataset variable weight has the value: 84 The dataset variable weight has the value: 98 NOTE: There were 3 observations read from the data set SASHELP.CLASS.

La instrucción macro% IF resuelve la variable de macro y compara el valor resuelto de esa variable de macro con el height cadena de texto. Observe que no se necesitan (o se desean) comillas en la instrucción% IF. Debido a que el lenguaje de macro es para el procesamiento de texto, no utiliza comillas para indicar un valor de texto.

En resumen, utilice la instrucción macro% IF para tomar decisiones basadas en los valores de texto almacenados en variables macro para controlar qué código de paso de datos genera el lenguaje de macros, y utilice el enunciado IF de pasos de datos para tomar decisiones basadas en el valor de los datos variables de paso para controlar qué código de paso de datos se ejecuta. (Los nombres de las variables de paso de datos a los que se hace referencia en una instrucción IF se pueden generar utilizando variables macro, o incluso macros).

Comprender la diferencia entre% PUT vs PUT,% IF vs IF,% DO vs DO, etc. es un paso crítico en el aprendizaje de utilizar el lenguaje de macros.