Convertir de número a fecha cuando hay ceros

En algunas ocasiones nos encontramos que en una tabla los campos de fecha aparecen en numérico y llevan los valores no informados rellenados con un 0. O sea, hay un 0 en vez de un nulo. En este artículo quiero ofreceros algunas opciones para convertir rápidamente estos números en un formato fecha de SAS tradicional, de forma que podamos operar normalmente con ellos. Veremos ejemplos cuando el campo de origen es de texto, o es numérico.

En primer lugar, una tabla para los ejemplos que van abajo:

data EJEMPLO;
fecha_inicio = 20220101;
fecha_fin = 20220331;
output;
fecha_inicio = 20220101;
fecha_fin = 0;
run;

Formato número YYYYMMDD a fecha


data FECHAS1;
    set EJEMPLO;
    format fc_inicio ddmmyyn8.;
    if fecha_inicio = 0 then fc_inicio = .;
    else fc_inicio = mdy(mod(floor(fecha_inicio/100),100),mod(fecha_inicio,100),floor(fecha_inicio/10000));
run;

Formato número DDMMYYYY a fecha


data FECHAS2;
    set EJEMPLO;
    format fc_fin ddmmyys10.;
    if fecha_fin = 0 then fc_fin = .;
    else fc_fin = mdy(mod(floor(fecha_fin/10000),100),floor(fecha_fin/1000000),mod(fecha_fin,10000));
run;

Convertir mes YYYYMM a fecha

A veces tienes un dato de fecha expresado como mes. El problema para crear una fecha a partir de él es que no conocemos el día, así que hay que asumir que nos valdría o el primer o el último día del mes. La forma de convertirlo es así:


data FECHAS3;
    mes = 202208;
    format fc_mes_1 fc_mes_2 ddmmyys10.;
    /* primer día del mes */
    fc_mes_1 = mdy(mod(mes,100),1,floor(mes/100));
    /* último día del mes */
    fc_mes_2 = intnx('month',mdy(mod(mes,100),1,floor(mes/100)),0,'e');
run;

Para saber algo más de los tipos de formato de fecha que puedes utilizar visita este link.

SAS: Operaciones con cadenas de texto

La verdad es que SAS tiene un montón de funciones para tratar cadenas de texto. Y algunas de ellas son muy divertidas a la hora de programar por la cantidad de trabajo que te ahorran.
Vamos a empezar por algunas de las más típicas, las funciones para limpiar cadenas y quitar espacios. Vamos a utilizar la cadena como ejemplo:

%let cad = '  En un lugar de la  Mancha...  ';
Función Resultado Comentario
strip(&cad) ‘En un lugar de la Mancha…’ Elimina los espacios de los extremos, pero no los duplicados en el medio de la cadena.
compress(&cad) ‘EnunlugardelaMancha…’ Elimina todos los espacios de la cadena.
compbl(&cad) ‘ En un lugar de la Mancha… ‘ Elimina los espacios duplicados dejando uno solo. Deja al menos un espacio en los extremos si existían previamente.

Probablemente en algunas ocasiones sea bueno combinar algunas de ellas, como por ejemplo, para eliminar los espacios del inicio y del final y asegurarse de que no existen espacios dobles en la cadena podemos utilizar: strip(compbl(&cad)).

Tenemos también funciones para manejar mayúsculas y minúsculas.

%let cad = 'Iñigo fernández gonzález';
Función Resultado Comentario
upcase(&cad) ‘IÑIGO FERNÁNDEZ GONZÁLEZ’ Transforma la cadena a mayúsculas.
lowcase(&cad) ‘iñigo fernández gonzález’ Transforma la cadena a minúsculas.
propcase(&cad) ‘Iñigo Fernández González’ ‘Capitaliza’ todas las palabras de la cadena.

Otro tipo de funciones de texto son las que obtienen una subcadena a partir de una dada:
%let cad = 'Hélice de Watson & Crick';
%let fecha = "12/04/2021";

Función Resultado Comentario
substr(&cad,11,14) Watson & Crick Genera una cadena desde la posición 11 de la original y con 14 caracteres de longitud.
scan(&fecha,2,’/’) 04 Genera una cadena tomando el segundo trozo resultante de dividir la cadena indicada (&fecha) en trozos en función del carácter «/».

También tenemos funciones de búsqueda de una subcadena o de un carácter dentro de una cadena. Estas funciones pueden devolvernos la posición de la cadena buscada o sustituir la cadena buscada por otro valor:

%let cad = 'El sr. y la sra. Smith';
%let fecha = "12/04/2021";
Función Resultado Comentario
find(&cad,’Smith’) 18 Devuelve la posición de la primera ocurrencia de la subcadena buscada dentro de la cadena original.
index(&cad,’Smith’) 18 Devuelve la posición de la primera ocurrencia de la subcadena indicada.
translate(&fecha,’-‘,’/’) ’12-04-2021′ Sustituye uno a uno, uno o varios caracteres por otros en la cadena indicada.
tranwrd(&cad,’sr.’,’señor’) ‘El señor y la sra. Smith’ Hace lo mismo que la anterior, pero con grupos completos de caracteres.

Continuo mostrando más de estas funciones en la segunda parte de este artículo.

Cómo detener la ejecución en SAS

Hola de nuevo a todos. El tema de hoy es cómo detener el flujo de ejecución de un programa SAS. Normalmente lo haremos cuando se den determinadas condiciones, por ejemplo cuando un fichero no esté disponible, cuando se haya superado una hora de ejecución, etc.
Hay dos formas principales de detener la ejecución y utilizar una y otra depende del contexto dentro del programa:
Si estamos dentro de un paso data podemos utilizar el comando STOP.

data salida;
set entrada;
if _N_ = 100 then stop;
run;

Este ejemplo detendrá el proceso al llegar al registro número 100. La tabla de salida se obtendrá, pero sin el registro 100, por lo que se obtiene una tabla de 99 registros. El comando stop detiene la ejecución del paso data en el sentido de que no se procesan más registros pero no detiene la ejecución totalmente (ya que la tabla se genera).
En cambio, si estamos dentro de una macro utilizaremos una etiqueta y un comando %goto. Las etiquetas son identificadores a lo largo del código que identifican un punto determinado. En este caso tendríamos que situar esa etiqueta antes del %mend que termina la macro, y una condición que si se cumple lleve a esa etiqueta:


%macro ejecucion;
data salida1;
set entrada1;
run;
%if not %sysfunc(exist(entrada2)) %then %goto fin;
data salida2;
set entrada2;
run;
data salida3;
set entrada3;
run;
%fin:
%mend;
%ejecucion;

En este ejemplo el programa comprueba que exista la tabla «entrada2» antes de seguir con el proceso porque en caso contrario lleva el control de ejecución al final de la macro y la ejecución termina.

SAS: Convertir cadenas de texto a número o fecha

Hay varias operaciones que hay que hacer frecuentemente para convertir cadenas de texto a otros tipos de formato o a la inversa.

Empezaremos con lo más simple. Por ejemplo, para convertir un número a texto debemos de utilizar la función put() que admite como parámetro un número y devuelve el formato indicado (también se puede utilizar para dar formatos de fecha):

data salida;
    b = 1;
    b1 = put(b,$2.);
run;

Resultado de conversión número a texto
Y para la operación contraria, convertir una cadena en número, utilizamos la función input() que hace la operación inversa:

data salida;
    a = '1';
    a1 = input(a,8.);
run;

Resultado de conversión texto a número
Convertir una cadena de texto con una fecha en un campo fecha es un poco más complicado. Necesitamos tomar cada valor de mes, día y año de esa cadena e introducirlos como parámetros de la función mdy(). Pero mdy() solo admite números como parámetros por lo que debemos convertirlos con un input() previamente. Esto quedaría así:

data salida;
    f = '01/12/2020';
    mes = input(substr(f,4,2),8.);
    dia = input(substr(f,1,2),8.);
    anyo = input(substr(f,7,4),8.);
    format fecha ddmmyys10.;
    fecha = mdy(mes,dia,anyo);
run;

Convertir texto a fecha
De forma más directa y resumida podríamos expresarlo de la siguiente manera:

data salida;
    f = '25/12/2020';
    format fecha ddmmyys10.;
    fecha = mdy(input(substr(f,4,2),8.),input(substr(f,1,2),8.),input(substr(f,7,4),8.));
run;

Convertir texto a fecha
Únicamente debemos tener en cuenta con este método qué va a pasar con las fechas en los que el día y el mes vengan expresados por un solo dígito: ¿vendrán como 01 o como 1? Para resolver este punto podemos cambiar nuestro substr() por un scan(). Esta función divide una cadena por el carácter que se le indique y nos devuelve la subcadena que ocupe la posición indicada por parámetro. Para el caso anterior, lo expresaríamos así:

data salida;
    f = '01/12/2020';
    mes = input(scan(f,2,'/'),8.);
    dia = input(scan(f,1,'/'),8.);
    anyo = input(scan(f,3,'/'),8.);
    format fecha ddmmyys10.;
    fecha = mdy(mes,dia,anyo);
run;

Convertir texto a fecha
Convertir una fecha en una cadena de texto se consigue por la combinación de las funciones put() e input(). El put() que va en el interior sirve para poner la fecha en el formato adecuado antes de convertirlo en texto. En caso contrario la fecha se convertirá como el número que es, en texto. Una vez tenemos el formato adecuado lo convertimos a texto con un input().

data salida;
    fecha = '25dec2020'd;
    fechado = input(put(fecha,yymmddn8.),$8.);
run;

Convertir fecha a texto