Monográficos. CALL SYMPUT imprescindible

16 Feb

He detectado que muchas búsquedas que llegan a Análisis y Decisión vienen por la palabra clave «call symput». Por este motivo me he decidido a escribir este rápido monográfico sobre esta instrucción. Con un par de ejemplos podemos familiarizarnos con su funcionamiento.CALL SYMPUT es una rutina de SAS que nos permite crear macro variables durante la ejecución de un paso data, digamos que es un mecanismo que comunica el compilador del macro lenguaje SAS con el propio lenguaje SAS. El ejemplo prototípico de su uso, determinar el número de observaciones de un dataset que cumplen determinada condición:


*DATASET ALEATORIO;
data uno;
 do cliente=1 to 1000;
 importe=ranuni(9)*10000;
 output;
 end;
run;
*NUMERO DE CLIENTES CON IMPORTE > 2000;
data _null_;
 set uno (where=(importe>2000)) end=final;
 if final then call symput('nobs',_n_);
run;
%put _user_;

Partimos de un dataset aleatorio con 1000 observaciones y necesitamos introducir en una macro variable cuantas observaciones tienen un importe mayor a 2000. Vemos que generamos la macro variable nobs a partir de la variable automática _n_ en el momento en que se finaliza la lectura del dataset uno. Hay que tener especial cuidado con el formato que toman las macro variables en la tabla de símbolos ya que los espacios que deja a la izquierda pueden generarnos algún contratiempo, se recomienda dar formatos como hacemos en el siguiente ejemplo. Si deseamos introducir en 3 macros los valores del mínimo, mediana y máximo podemos emplear el proc univariate y call symput:


ods result;
ods output Quantiles = cuan;
proc univariate data=uno ;
var importe;
quit;
data _null_;
 set cuan;
 if quantile="100% Máx" then call symput ('max',compress(put(estimate,8.1)));
 if quantile="0% Mín" then call symput ('min',compress(put(estimate,8.1)));
 if quantile="50% Mediana" then call symput ('med',compress(put(estimate,8.1)));
run;
%put _user_;

Una forma práctica de trabajar con percentiles. Es importante que las macro variables tengan un formato adecuado. Otro ejemplo de uso de CALL SYMPUT es la generación de arrays de macro variables, por ejemplo generar macro_1 a macro_20 con valores aleatorios:

data _null_;
 do i=1 to 20;
 call symput ('macro'||compress("_"||put(i,8.)),ranuni(4));
 end;
run;
%put _user_;

Con estos ejemplos espero que se entienda su uso. En el trabajo diario con SAS, es una de las rutinas más utilizadas. Como siempre, si tenéis dudas, sugerencias o un trabajo bien retribuido mi dirección de correo es r_vaquerizo@analisisydecision.es

8 respuestas a «Monográficos. CALL SYMPUT imprescindible»

  1. Hola, buen día!

    Estoy usando call symput en una macro, y según el funcionamiento de ejecución de un data que he percibido(ejecución de instrucciones para cada registro), tendría que asignarme un valor diferente cada vez que cambia de registro o de fila, sin embargo, esto no lo esta haciendo y no he podido identificar la razón.

    %macro aterr();
    %let var=0;
    Data cerrados_prueAt2;
    set cerrados_prueAt;

    %do An = %eval(&anio_iin.) %to &anio_fSdo.;
    %do Me=1 %to 12;

    %let fech_cicl = %sysfunc(mdy(&me.,1,&an.));

    call symput («fech»,fecha_incumpIni);

    %IF &fech_cicl. = &fech. %THEN %do;
    %let i= 0;
    ME_&i.= Sdo_&An._&me._pos;
    %let i=%eval(&i+1);

    %end;
    %ELSE %IF &fech_cicl. > &fech. %THEN %do;
    ME_&i. = Sdo_&An._&me._pos;%put primer: &i;
    %Let i=%eval(&i+1);

    %end;
    %if &An. = &anio_fSdo. and &Me. = 12 %then %do;
    %let i=0;
    %end;

    %end;
    %end;
    output;
    run;

    %mend;

    %aterr();

    Si pudiesen por favor darme alguna idea.

  2. Hola, este problema le hemos tenido todos alguna vez. No te cambia el valor de la macro. En vez de macro variables emplea variables del propio conjunto de datos SAS. Resulta más fácil.

  3. Hola,
    Respecto del primer ejemplo: una vez creas las macro – variables para los cuantiles, ¿ cómo haces para llamarlas posteriormente? porque el fichero cuan no se modificaría en caso de tener espacios en blanco a la izquierda…en general, una vez se crean las macro – variables, como se llaman?

    Saludos y gracias!

  4. hola,

    tengo un problema: quiero que call symput me almecene en una macrovariable todos los registros que tengo en una librería y que se refieren al nombre de los datasets que contiene y al llamar a %put, me los liste se llaman datasetn_1,2,3…y sólo me devuelve el primer archivo:

    data _null_;
    set archivos;
    where index(lowcase(nombrearchivos),»sas7bdat»)>1;
    CALL SYMPUT (‘miarchivos’,(lowcase(nombrearchivos)||»sas7bdat»));
    run;

    %put :&miarchivos;

    me resuelve;

    14 GOPTIONS ACCESSIBLE;
    SYMBOLGEN: Macro variable MIARCHIVOS resolves to datasetn_1.sas7bdat

    sas7bdat
    15 %let files=&miarchivos;
    16 %put file ok: &files;
    SYMBOLGEN: Macro variable FILES resolves to datasetn_1.sas7bdat

    sas7bdat
    file ok: datasetn_1.sas7bdat

    Gracias,

    Aliciann1

  5. Hola Alicia, te está cogiendo el último registro.

    Para complicarte menos:

    proc sql noprint;
    select nombrearchivos||».sas7bdat» into: miarchivos separated by » »
    from archivos
    where index(lowcase(nombrearchivos),”sas7bdat”)>1;
    quit;

    • Hola Raul,

      prescindo de ||”.sas7bdat es decir de la extensión, quito los separadores y tal como:

      proc sql noprint;
      select nombrearchivos into: miarchivos
      from archivos
      where index(lowcase(nombrearchivos),’Zz’)>1;
      quit;
      %put &miarchivos;

      y me almacena en la macrovariable ‘miarchivos’ todos los ficheros cuyo nombre comience por ‘Zz’ y funciona Ok.

      Una duda importante es que por ejemplo la librería dictionary que explicaste en otro post, ‘Unión de múltiples tablas SAS con un nombre parecido’ a mí en Guide no me funciona.

      Saludos y gracias

  6. Hola Mario,
    antes de preguntarte he buscado por todos los sitios posibles y no veo la solución.
    tengo una tabla que es prueba_cuenta con la variable CODCVACO y otra tabla que es
    Performing_mex_20161231 con la variable cuenta, trato de hacer que cada valor de cuenta me lo encuentre en codcvago, pero solo me lo hace con el último valor que teien cuenta de la tabla de Performing_mex_20161231, es decir, no me coge valor a valor….
    Me podrias ayudar?
    Mil gracias

    %macro P0904 (fecha,pais);

    %DO I=1 %to 311;
    DATA _NULL_;
    SET Performing_mex_20161231;
    call symput (‘PER’, COMPRESS(CUENTA));
    RUN;

    proc sql ;
    create table PRUEBA as
    select t1.*
    FROM PRUEBA_cuenta t1
    WHERE
    input(put(&PER.,10.),10.) eq substr(CODCVACO,1,length(input(put(&PER.,10.),10.)));
    QUIT;
    %end;
    %mend;
    %P0904 (&fecha.,&pais.);

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *