BookmarkSubscribeRSS Feed
Tip Semanal 034: Funciones de SAS (parte 4 - función put y sus variantes).sas
Berenice25
SAS Employee

La cuarta parte de los Tips de funciones profundiza el uso de la función put y presenta dos de sus variantes. 
Continuamos así con la serie de Tips de funciones de SAS: 028, 029 y 033. 

Comenzaremos viendo otro uso de la función put. 
Y continuaremos viendo ejemplos de las funciones putn y putc, que son dos alternativas de la función put. 

 

Para más información sobre el uso de put, putn y putc pueden ver: 
https://blogs.sas.com/content/sgf/2015/05/01/converting-variable-types-do-i-use-put-or-input/ 
https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.2/lefunctionsref/p12zqzvwx4dv6kn1p9crijxswolk.h...
https://support.sas.com/resources/papers/proceedings/proceedings/sugi25/25/aa/25p002.pdf 
https://documentation.sas.com/doc/es/pgmsascdc/9.4_3.5/lefunctionsref/n1en5ed71v1ai3n1pxwx2rskgz7g.h...

 

 


						/*------------------*/
						/* 					*/
						/* 		Tip 034		*/
						/* 					*/
						/*------------------*/
						/*------------------*/


/************************************************************************/
/* 								  										*/
/* 						Funciones de SAS (parte 4)  					*/
/* 							  											*/
/************************************************************************/




/************************************************************************/
/*																		*/
/* Lo que haremos es seguir la siguiente secuencia:						*/
/* 		1. Otro uso de la función put									*/
/* 		2. Uso de la función putn										*/
/* 		3. Uso de la función putc										*/
/*																		*/
/************************************************************************/




/************************************/
/*									*/
/* 1. Otro uso de la función put 	*/
/*									*/
/************************************/

 

En el Tip 033 habíamos visto que la función put se utiliza para transformar una variable numérica en alfanumérica.
Lo que no vimos es que esta función tiene un uso más general. A eso nos dedicaremos: 

La función put siempre crea una variable alfanumérica. Pero puede crearla a partir de una variable numérica (como ya vimos)... ¡o también a partir de una variable alfanumérica! 

Entonces: 
variable numérica --> <función put> --> variable alfanumérica 
variable alfanumérica --> <función put> --> variable alfanumérica 

 

La forma general de escribir la función put es: 
PUT(<variable o constante>, formato.); 

Pregunta: ¿Y si estamos creando una nueva columna usando 'put', cuál será su ancho? 
Respuesta: Será el mismo del ancho del formato utilizado en la función. 

Veamos entonces un ejemplo de como utilizar esta función sobre una variable alfanumérica:

 

*----------------------------------------------------------------------*/
/* Ejemplo: conversión una variable alfanumérica en otra del mismo tipo	*/
/*----------------------------------------------------------------------*/

/* Cómo modificar la longitud y el formato de una variable de texto partiendo de otra 	*/
/* variable de texto?																	*/
/* Usando length puedo crear una nueva variable con una longitud distinta a la original.*/
/* Y usando format puedo modificar el formato de salida, pero no el formato que hereda 	*/
/* de la variable original.	Estas sentencias están comentadas en el siguiente código 	*/
/* para que podamos hacer pruebas.														*/
/*																						*/
/* Pero entonces...¿Por qué no intentar con la función put?								*/

data prueba_put;
	*length nueva $ 10;
	numero='  1234';
	texto='?AbCdE!';
	nueva=texto;   /* salvo que utilicemos la sentencia 'length', la variable 'nueva' 
					tendrá la misma longitud que la variable 'texto' */
	*format nueva $upcase18.;   /* ¡format no cambia la longitud de la variable! */
	yy=put(numero,$quote8.);   /* con put la longitud y el formato de la nueva 
								variable cambian */
	zz=put(texto,$reverj10.);  /* con put la longitud y el formato de la nueva 
								variable cambian */
	
run;

Hemos visto un ejemplo donde la función input se utiliza para crear nuevas variables alfanuméricas con longitud y formato diferentes de las originales. 
Pasemos ahora a una situación más compleja... 
Imaginemos el siguiente escenario: tenemos una tabla con una variable con números enteros (que en realidad son días de SAS) y otra variable clave (key).
Y necesitamos una nueva variable de tipo carácter cuyos valores tengan fechas con distintos formatos, dependiendo de esa variable clave (key). Para poder resolverlo pasaremos al segundo punto de nuestra secuencia:

 

 

/************************************/
/*									*/
/* 2. Uso de la función putn	 	*/
/*									*/
/************************************/


/*----------------------------------------------------------*/
/* Ejemplo: escenario con formatos dependiendo de una clave	*/
/*----------------------------------------------------------*/

/*----------------------------------*/
/* Etapa 1: creo la tabla de prueba */
/*----------------------------------*/

/* Comenzamos con nuestro escenario: creamos la tabla inicial.						*/
/* Esta tabla incluye las 2 variables ('dias' y 'clave') que habíamos mencionado 	*/
/* más arriba.																		*/

data dias_sas;
	input dias clave;

	datalines;
365 1
-1 2
21231 1
20337 3
23025 2
0 3
;
run;



/*------------------------------------------------------------------------------------------*/
/* Etapa 2: nueva variable con formatos dependendiendo de una variable que sirva como clave */
/*------------------------------------------------------------------------------------------*/

/* Para lograr nuestro propósito vamos a intentar con varias alternativas, lo que nos 	*/
/* permitirá analizar ventajas y desventajas.											*/

/* Supongamos -por ejemplo- que:					*/
/* 	el valor 'clave=1' usa el formato 'date9.' 		*/
/* 	el valor 'clave=2' usa el formato 'ddmmyy10.'	*/
/* 	el valor 'clave=3' usa el formato 'yymmdd10.'	*/



/*--------------------------*/
/* Etapa 2 - Alternativa 1 	*/
/* If...then + format		*/
/*--------------------------*/

/* Después de pensar un buen rato decidimos que, como el formato depende de los 	*/
/* valores de la variable 'clave', vamos a intentar con un 'if.. then' + una 		*/
/* sentencia 'format'. Un razonamiento digamos... 'clásico'.						*/															

data dias_nueva_alt1;
	set dias_sas;
	fecha=dias; /* la nueva variable */

	if clave=1 then
		do;
			format fecha date9.;
		end;
	else if clave=2 then
		do;
			format fecha ddmmyy10.;
		end;
	else if clave=3 then
		do;
			format fecha yymmdd10.;
		end;
run;

La idea es linda, pero se puede ver en el resultado que ¡no funciona! 
Podemos ver que es lo que sucede usando el 'debugger' del Paso Data, si es que usan Enterprise Guide. 
O también podemos hacer unas prueba, por ejemplo intercambiando los 2 formatos. 
O alcanzaría cambiando el último formato. 
¿Qué es lo que está sucediendo? Es que el Paso Data tiene 2 etapas: 
1.- Compilación: aquí crea la estructura de la nueva tabla, el vector de trabajo (Program Data Vector) y demás. Y los nombres y el tipo de cada variable son parte de la estructura. 
2.- Ejecución: aquí trabaja con los valores de la/s tabla/s. 
Y la sentencia 'format' se aplica en la etapa de Compilación. Pero modificar el formato dependiendo de los valores de la tabla (en este caso de la variable 'clave'), forma parte de la etapa de Ejecución. 
Y como el formato ya fue creado en la etapa anterior (en Compilación), por eso no se modifica. Tal como lo estamos comprobando.

 

/*--------------------------*/
/* Etapa 2 - Alternativa 2 	*/
/* Función put				*/
/*--------------------------*/

/* Después de no haber tenido éxito con la alternativa 1, vamos a intentar 			*/
/* reemplazando la sentencia format con una función put. 							*/

data dias_nueva_alt2;
	set dias_sas;

	if clave=1 then
		do;
			fecha=put(dias,date9.);
		end;
	else if clave=2 then
		do;
			fecha=put(dias,mmddyy10.);
		end;
	else if clave=3 then
		do;
			fecha=put(dias,yymmdd10.);
		end;
run;

¡Una maravilla! ¡Este código funciona! Salvo la última cifra del día, cosa que habrán notado y que saben cómo resolver.
Pero claro, está harcodeado. Es decir que no es simple cambiarlo en el caso de que nos soliciten modificar los formatos que dependen de las claves. Lo que puede ser todo un problema. 
Entonces, ¿se puede generar un código que permita modificar fácilmente los formatos dependiendo de los valores de la variable?

Veamos...

 

/*------------------------------*/
/* Etapa 2 - Alternativa 3 		*/
/* Funciones put y putn			*/
/*------------------------------*/

/* Vamos a usar la función put y la función putc. */ 


/* En primer lugar creamos el formato que relaciona las claves con los formatos de fecha */

proc format;
   value fecha_num_fmt 	1='date9.' 
                 		2='mmddyy10.'
						3='yymmdd10.';
run;

/* Ahora combinamos las funciones put y putn */

data dias_nueva_alt3;
	set dias_sas;
	length fecha $ 20;
	var_fecha_fmt=put(clave,fecha_num_fmt.); /* para que el formato cambie según el 
												valor de la 'clave' */
	fecha=putn(dias,var_fecha_fmt); /* ¡putn acepta una variable como formato! */
	drop var_fecha_fmt;
run;

El truco está en que la función putn acepta formatos clásicos (los que terminan con un punto) y también formatos que no terminan con un punto, ¡por lo que se pueden utilizar variables! 
Si se quieren hacer modificaciones en los formatos, se hacen dentro del proc format. Ya que la función putn ¡permite especificar un formato en tiempo de ejecución! 
¡Y el código en mucho más eficiente! 

Hemos visto la ventaja de usar la función putn. Como podrán imaginar, la función putc trabaja de manera similar. Eso sí, ahora las variables serán alfanuméricas.

 

/************************************/
/*									*/
/* 3. Uso de la función putc	 	*/
/*									*/
/************************************/

/*--------------------------------------------------------------------------*/
/* Ejemplo: escenario con formatos dependiendo de una clave alfanumérica	*/
/*--------------------------------------------------------------------------*/

/*----------------------------------*/
/* Etapa 1: creo la tabla de prueba */
/*----------------------------------*/

data prueba_putc;
	input Producto_Linea $ Descuento $;
	datalines;
L1 B
L2 A
L2 A
L2 B
L1 C
L1 B
L1 B
L1 A
L1 A
L2 C
L2 B
L1 C
;
run;


/*---------------------------*/
/* Etapa 2: creo un formato	 */
/*---------------------------*/

proc format; /* el 'f_' es necesario porque sino no funciona putc (ver más abajo);
				en realidad alcanza con escribir uno o más caracteres, no importa 
				cuales sean */ 
	value $ f_L1_Fmt	"A" = "aplicar descuento de $15"  /* por valores fijos */
						"B" = "aplicar descuento de $25"
						"C" = "aplicar descuento de $25"
	;
	value $ f_L2_Fmt	"A" = "aplicar descuento del 10%"  /* por porcentajes */
						"B" = "aplicar descuento del 20%"
						"C" = "aplicar descuento del 25%"

	;
run;


/*---------------------------------------------------------------*/
/* Etapa 3: usamos el formato sobre la tabla que habíamos creado */
/*---------------------------------------------------------------*/

data resultado_putc;
	set prueba_putc;
	length Descuento_descrip $44; /* la longitud de la nueva variable */
	temp=cats('$f_',Producto_Linea,'_Fmt'); /* concatena, remueve espacios al principio y 
												al final, y guarda el formato en una  
												variable temporal */
	Descuento_descrip = putc(Descuento,temp); /* como con putn, putc acepta una variable como formato */
	drop temp;
run;

Hemos visto que las funciones putn y putc permiten extender las posibilidades de la tradicional función put. 
Y también hemos comprobado lo sutil que puede ser saber distinguir y controlar las etapas de Compilación y Ejecución en el Paso Data. 
Desde ya que nos quedaron varias posibilidades pendientes, pero se las dejamos para que las piensen; e intenten resolverlas...

 

/*-------------------*/
/* fin del código 	 */
/*-------------------*/

 

1 Comment

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

Article Labels
Contributors