2011-06-09 25 views
5

Supongamos que permiten al usuario escribir su propia macro cálculo variable usando una interfaz de usuario común:¿Cómo puedo realizar una pieza de macro para cada observación en el paso de datos sas?

%macro calculate(var_name, var_value); 
%* Some user-defined calculation; 
%mend calculate; 

Luego, en un paso de datos, que puede calcular una nueva variable con el definido por el usuario macro:

data dataset; 
    set dataset; 
    new_var = %calculate('variable1', variable1); * This doesn't work. It just shows my indication. 
run; 

Donde variable1 es una variable en el conjunto de datos. Aquí, quiero pasar el nombre de la variable y el valor real de la variable. Después del cálculo, coloque el valor en new_var.

¿Cómo puedo lograrlo?

+0

se le dará un ejemplo del tipo de cálculo definida por el usuario que está esperando? –

Respuesta

3

Usted puede hacer este trabajo, pero es probable que esté escribiendo la macro incorrectamente. Debe recordar que las macros SAS son esencialmente preprocesadores de texto: ingresan el código que ha escrito y el código de salida para alimentar a SAS [1].

Así que aquí es un simple "adición" macro:

%macro calculate (var_name, var_value); 
    &var_name + &var_value; 
%mend; 

data one; 
    input [email protected]@; 
    b = %calculate(a, 3); 
    c = %calculate(a, a); 
cards; 
1 3 -2 4 
; 
run; 

proc print data=one; 
run; 

La instalación macro reemplazará el %calculate bits con el código generado por la macro, y SAS será la que vea lo siguiente:

%macro calculate (var_name, var_value); 
    &var_name + &var_value; 
%mend; 

data one; 
    input [email protected]@; 
    b = a + 3; 
    c = a + a; 
cards; 
1 3 -2 4 
; 
run; 

proc print data=one; 
run; 

se puede ver por sí mismo en el archivo de registro con la declaración options mprint

por desgracia, esto no va a cubrir una ll cálculos potenciales. Es posible que desee buscar PROC FCMP para obtener una forma de generar funciones/subrutinas personalizadas utilizables en el paso DATA.

[1] Sé que es más complicado que eso, pero se puede pensar mucho así.

+0

Esto es algo similar a cómo recodizo una variable en particular. Varios conjuntos de datos requieren un recod de estados australianos. El código se ejecuta en varias líneas. Como el código es bastante directo y se necesita en una serie de programas, prefiero almacenarlo en una macro y realizar una simple llamada dentro de cada programa, guardando siete líneas de código. – Murray

+0

+1 para responder a la pregunta y para mencionar PROC FCMP - FCMP es definitivamente el camino a seguir. Ver la respuesta de cmjohns a continuación para un ejemplo. –

6

¿Es necesario que lo logre con macros? Esto suena como una situación en la que PROC FCMP sería más útil ya que le permite definir sus propias funciones o subrutinas (fcmp = "compilador de funciones") que pueden usarse en un paso de datos como una función incorporada.

Aquí está un ejemplo sencillo:

proc fcmp outlib=sasuser.funcs.math; 
    function calc(var); 
    newvar=log(var); /*user defined stuff here - can be simple or complex*/ 
    return(newvar); 
    endsub; 
run; 

option cmplib=sasuser.funcs; /*tell SAS where to look for functions*/ 
data _null_; 
    set sashelp.class; 
    newvar=calc(height); /*call your new function */ 
    put newvar=; 
run; 
+0

Buen punto. Para esta pregunta, la respuesta de Aniko está más cerca de lo que estoy buscando y es más simple. Pero definitivamente voy a mirar en proc fcmp. Gracias por compartir el conocimiento. – Steve

0

Este es un punto común de confusión. El problema es que SAS procesa todos los códigos macro en su programa ANTES de cualquiera de los códigos regulares. Por lo tanto, cuando llama al %calculate('variable1', variable1);, todavía no tiene acceso a los datos en el conjunto de datos.

Dicho esto, sería más fácil ayudarle a encontrar una solución si tuviera un ejemplo de lo que podría querer decir con %*Some user-defined calculation;.

2

Sé que esta es una publicación anterior, pero creo que vale la pena mencionar esto.

Aquí hay una solución que permite usar una rutina de macro como lo haríamos con una función. Esto se logra con la ayuda de la función SAS resolve(). Lo que sigue a "% then" (en este caso es texto pero podría ser un número) corresponde a lo que pondríamos en la parte return() de una "función real".

%macro compare(v1, v2); 
    %if &v1 > &v2 %then v1 is greater than v2; 
    %else v2 is greater than v1; 
%mend; 

data check (drop = macroCall); 
    input v1 v2; 
    macroCall = cats('%compare(', v1, ',', v2, ')'); 
    result = resolve(macrocall); 
    datalines; 
1 2 
2 1 
; 

Resultados:

v1 v2 result 
1 2 v2 is greater than v1 
2 1 v1 is greater than v2 
Cuestiones relacionadas