macros en sas - sasCommunity.org

Anuncio
RDSUG 01
Experiencia de Uso
Paper 2014-002
MACROS EN SAS
JUAN RADHAMES
G ÓMEZ M ARTÍNEZ
RESUMEN (ABSTRACT)
El macro lenguaje de SAS es una de las herramientas más poderosas que provee SAS. Este lenguaje si es
utilizado de una manera correcta nos permite la realización de una serie de actividades que de otra forma
implicarían la escritura de un sinnúmero de líneas de código y sobre todo la eficientización de procesos.
En este documento presentamos el concepto de macros y macro variables, como pueden ser utilizadas, así
como también dos ejemplos puntuales de cómo los macros nos pueden ayudar en términos de eficiencia y
estandarización.
Al concluir este documento pretendemos que usted conozca la diferencia entre una macro variable y un macro
y la manera en que estos pueden interactuar para la generación de un programa eficiente.
CONCEPTOS
Macros, macro variables.
MACROS EN SAS
CONCEPTO DE MACRO
Una macro (del griego μακρο, makro, que significa ‘grande’) - es una abreviatura de macroinstrucción- y aparte
es una serie de instrucciones que se almacenan para que se puedan ejecutar de manera secuencial mediante
una sola llamada u orden de ejecución. Dicho de otra manera, una macroinstrucción es una instrucción
compleja, formada por otras instrucciones más sencillas. Esto permite la automatización de tareas repetitivas.
(Wikipedia).
Más propiamente dentro del lenguaje, SAS provee una herramienta para la utilización de macros que permite
reducir la cantidad de texto que debemos escribir para realizar tareas comunes. El procesador de macros lee el
macro lenguaje y transforma el código ya revisado en un programa de SAS.
En SAS existen dos formas en las que nos referimos a los macros:
Las macro variables, las cuales se pueden referenciar bajo la siguiente nomenclatura &name.
Y los macros que pueden ser referenciados utilizando la nomenclatura %name.
RDSUG 01
Experiencia de Uso
MACRO VARIABLES
Las macro variables se utilizan en SAS para reemplazar cadenas de texto dentro del código. La manera mas
simple de definir una macro variable es utilizando la sentencia %LET.
%LET texto = Esto es una prueba
%PUT el valor de texto es &texto.
En este ejemplo al hacer referencia a la variable texto, lo que se imprime en el log de SAS es: el valor de texto
es Esto es una prueba.
Otra manera de crear macro variables dentro de un data step es utilizando la expresión SYMPUT. Al llamar a
esta expresión debemos pasar dos parámetros, el primero el nombre la macro variable que queremos crear y
asignar un valor y el segundo parámetro es el valor a asignar.
Es bueno destacar que el valor de la macro variable solo estará disponible luego de ejecutado el data step.
DATA _NULL_;
Fecha = today();
Call symput(“fecha”, fecha);
RUN;
MACROS
Los macros son programas compilados que pueden ser llamados dentro de un programa de SAS o desde la
línea de comandos de SAS. Al igual que con las macro variables, los macros se utilizan para generar texto. Sin
embargo los macros poseen cualidades adicionales como:
Los macros pueden tener sentencias de programación que nos permiten indicar cómo y cuando el
texto va a ser generado.
Los macros aceptan parámetros. Estos nos permite generar macros genéricos que pueden tener
múltiples usos.
Para que un macro pueda ser compilado, se debe generar una definición de macro. La forma general para esta
definición es la siguiente:
RDSUG 01
Experiencia de Uso
%MACRO nombre_macro;
<texto_macro>
%MEND <nombre_macro>;
Donde nombre_macro es el nombre único de SAS que identifica el macro y texto_macro es cualquier
combinación de sentencias, llamadas a macros, expresiones o constantes de texto.
%MACRO primer_macro;
PROC PRINT DATA=SALES;
TITLE1 “TESTING MY FIRST MACRO”;
%MEND primer_macro;
%primer_macro;
POR QUE UTILIZAR MACROS
La utilización de macros provee un sinnúmero de ventajas dentro de las que podemos mencionar;
Generación automática de código SAS.
Reducen el esfuerzo requerido para leer y escribir código SAS.
Reutilización de código.
Permite la utilización de parámetros.
Permiten controlar el flujo de ejecución de un programa, dentro de un macro podemos utilizar
sentencias iterativas y de condición que abarcan a más de un data step.
Eficientizacion de Código.
EJEMPLOS DE MACROS EN SAS
Reporte personalizado a una lista de correos.
%macro reporte(codigo,nombre,email);
%ventas(&codigo.);
%let mailTo = "&email.";
%let mailFrom = "[email protected]";
%let mailCC = "[email protected]";
RDSUG 01
Experiencia de Uso
filename mymail EMAIL
from
= &mailFrom.
To
= (&mailTo.)
CC
= &mailCC.
Subject = "Reporte"
ct
='text/html'
;
ods
ods
ods
ods
ods
ods
ods
ods
los
ods
por
ods
ods
ods
html body=mymail style=seaside rs=none ;
html text='<div align="left">Buenos Dias </div>';
html text="<div>Sres. &nombre. </div>";
html text='<br>';
html text='<br>';
html text='<div align="left">Distinguido Cliente, </div>';
html text='<br>';
html text="<div align=>En cumplimiento los acuerdos realizados, anexo
reportes de ventas al <b> &mesano. </b>.
html text="<div align=>Cualquier duda o sugerencia acerca del Reporte
favor canalícenla a través de su representante</div>";
html text="<br><br>";
html text="<div align=>Saludos!</div>";
html text="<br><br>";
proc report data=sales HEADLINE HEADSKIP nowd missing split="\"
style(header)=[foreground=white background=crimson bordercolor=black]
style(column)=[bordercolor=black ];
columns nombre (ventas, MES_BO);
DEFINE nombre / GROUP 'Cliente';
DEFINE Mes / across 'Mes';
define ventas / Ventas Brutas' format=comma10.2;
title1 '<b>Ventas Brutas
run;
ods html close;
quit;
%mend;
DATA WORK.correo_clientes;
LENGTH
Codigo
$ 4
Nombre
$ 64
Estatus
$ 8
email
$ 105
;
FORMAT
</b>';
RDSUG 01
Experiencia de Uso
codigo
Nombre
Estatus
email
;
INFORMAT
codigo
nombre
Estatus
email
$CHAR4.
$CHAR64.
$CHAR8.
$CHAR105.
$CHAR4.
$CHAR64.
$CHAR8.
$CHAR105.
;
INFILE &ruta..correo_clientes.txt"
DELIMITER='09'x
LRECL=400
MISSOVER
DSD
firstobs=2;
INPUT
Codigo $
Nombre
$
Estatus
$
email
$
RUN;
proc sql;
select count(codigo) into :cantidadclientes
from correo_clientes(where=(^ missing(email)));
%let cantidadClientes = & cantidadclientes;
quit;
proc sql;
select codigo, nombre_dealer, email
into :codigo1 - :codigo& cantidadclientes, :nombre1
cantidadclientes., :email1 - :email& cantidadclientes.
from correo_clientes (where=(^ missing(email)));
quit;
%macro enviaEmail;
%do i=1 %to & cantidadclientes;
%let codigo = &&codigo&i;
%let nombre = &&nombre&i;
%let email = &&email&i;
%reporte(&codigo.,&nombre.,&email.);
%end;
%mend;
%enviaEmail;
-
:nombre&
RDSUG 01
Experiencia de Uso
Ejemplo de Eficiencia de Código
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
%let
enero2013 = work.SALE_EST_JAN2013;
febrero2013 = work.SALE_EST_FEB2013;
marzo2013 = work.SALE_EST_MAR2013;
abril2013 = work.SALE_EST_APR2013;
mayo2013 = work.SALE_EST_MAY2013;
junio2013 = work.SALE_EST_JUN2013;
julio2013 = work.SALE_EST_JUL2013;
agosto2013 = work.SALE_EST_AUG2013;
septiembre2013 = work.SALE_EST_SEP2013;
octubre2013 = work.SALE_EST_OCT2013;
noviembre2013 = work.SALE_EST_NOV2013;
diciembre2013 = work.SALE_EST_DEC2013;
enero2014 = work.SALE_EST_JAN2014;
febrero2014 = work.SALE_EST_FEB2014;
marzo2014 = work.SALE_EST_MAR2014;
Abril2014 = work.SALE_EST_APR2014;
Mayo2014 = work.SALE_EST_MAY2014;
junio2014 = work.SALE_EST_JUN2014;
julio2014 = work.SALE_EST_JUL2014;
data resultado;
set ventas;
run;
proc sql noprint;
create table estatus_enero2013 as
select a.*, b.sale_status as estatus_enero2013
from resultado a
left join &enero2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_febrero2013 as
select a.*, b.sale_status as estatus_febrero2013
from estatus_enero2013 a
left join &febrero2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_marzo2013 as
select a.*, b.sale_status as estatus_marzo2013
from estatus_febrero2013 a
left join &marzo2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
RDSUG 01
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_abril2013 as
select a.*, b.sale_status as estatus_abril2013
from estatus_marzo2013 a
left join &abril2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_mayo2013 as
select a.*, b.sale_status as estatus_mayo2013
from estatus_abril2013 a
left join &mayo2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_junio2013 as
select a.*, b.sale_status as estatus_junio2013
from estatus_mayo2013 a
left join &junio2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_julio2013 as
select a.*, b.sale_status as estatus_julio2013
from estatus_junio2013 a
left join &julio2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_agosto2013 as
select a.*, b.sale_status as estatus_agosto2013
from estatus_julio2013 a
left join &agosto2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
Experiencia de Uso
RDSUG 01
quit;
proc sql noprint;
create table estatus_septiembre2013 as
select a.*, b.sale_status as estatus_septiembre2013
from estatus_agosto2013 a
left join &septiembre2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_octubre2013 as
select a.*, b.sale_status as estatus_octubre2013
from estatus_septiembre2013 a
left join &octubre2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_noviembre2013 as
select a.*, b.sale_status as estatus_noviembre2013
from estatus_octubre2013 a
left join &noviembre2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_diciembre2013 as
select a.*, b.sale_status as estatus_diciembre2013
from estatus_noviembre2013 a
left join &diciembre2013. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_enero2014 as
select a.*, b.sale_status as estatus_enero2014
from estatus_diciembre2013 a
left join &enero2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
Experiencia de Uso
RDSUG 01
create table estatus_febrero2014 as
select a.*, b.sale_status as estatus_febrero2014
from estatus_enero2014 a
left join &febrero2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_marzo2014 as
select a.*, b.sale_status as estatus_marzo2014
from estatus_febrero2014 a
left join &marzo2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_abril2014 as
select a.*, b.sale_status as estatus_abril2014
from estatus_marzo2014 a
left join &Abril2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_mayo2014 as
select a.*, b.sale_status as estatus_mayo2014
from estatus_abril2014 a
left join &Mayo2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
proc sql noprint;
create table estatus_junio2014 as
select a.*, b.sale_status as estatus_junio2014
from estatus_mayo2014 a
left join &junio2014. b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
Experiencia de Uso
RDSUG 01
Experiencia de Uso
Código Optimizado
proc sql;
create table estructura as
select MEMNAME,
input(substr(MEMNAME, 13), monyy7.) AS FECHA format=date9.,
compress(put(input(substr(MEMNAME, 13), monyy7.), espdfmn10.)
||
put(year(input(substr(MEMNAME, 13), monyy7.)), 4.)) AS nombre_var
from dictionary.tables
where libname = 'WORK' AND
memname like 'SALE_EST_%'
ORDER BY input(substr(MEMNAME, 13), monyy7.);
quit;
proc sql noprint;
select count(*) INTO :Cant_Tablas
from estructura ;
select memname,
nombre_var
into :tabla1-:tabla%left(&cant_tablas),
:nombre1-:nombre%left(&Cant_tablas)
from estructura;
quit;
%macro status ;
%do i=1 %to &cant_tablas;
%if &i=1 %then %do;
proc sql noprint;
create table estatus_venta as
select a.*, b.sale_status as estatus_&&nombre&i
from resultado a
left join WORK.&&tabla&i b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
%end;
%else %do;
proc sql noprint;
create table estatus_venta as
select a.*, b.sale_status as estatus_&&nombre&i
from estatus_venta a
left join work.&&tabla&i b
on a.cuenta = b.cuenta
and a.producto = b.producto
and a.plan = b.cod_plan;
quit;
%end;
%end;
%mend status;
%status;
RDSUG 01
Experiencia de Uso
CONCLUSIONES
La herramienta de macros que provee SAS es muy poderosa si sabemos dar un uso adecuado de la misma.
Puede ayudarnos como lo demuestran los ejemplos a agilizar la ejecución de procesos, así como también a
reducir las líneas de código que necesitamos, a través de la reutilización de procesos en los que solo debemos
cambiar el o los parámetros de entrada.
Lo importante es que podamos dar un uso adecuado a esta poderosa herramienta que nos provee SAS para
hacer nuestro trabajo más llevadero. Es un nuevo lenguaje dentro del lenguaje de SAS, pues presenta sus
reglas particulares, y debemos estar preparados para asumir el reto de utilizarlo.
REFERENCIAS
Breheny, Patrick. Writing cleaner and more powerful SAS code using macros.
01/11/2014 en http://myweb.uiowa.edu/pbreheny/talks/macros.pdf
Consultado en fecha
Cohen, John. A TUTORIAL ON THE SAS MACRO LANGUAGE. AstraZENECA LP.
SAS Institute Inc. 2004. SAS® 9.1 Macro Language: Reference. Cary, NC: SAS Institute Inc.
INFORMACIÓN DE CONTACTO
Comentarios y preguntas son apreciados. Contacte al autor
Nombre Autor
Juan Radhames Gómez Martínez
Claro RD.
INTEC
Email Trabajo: [email protected]
Email Personal: [email protected]
Redes Sociales
Twitter:radhixz
LikedIn:juan-gomez
SAS y cualquier otro nombre de producto o servicio de SAS Institute Inc., son marcas registradas de SAS
Institute Inc. Otras marcas y productos son marcar registradas de sus respectivas compañías.
Descargar