SAS

What about newer competition from free, open-source alternatives like R?

El tito Goodnight está más pendiente de IBM y Oracle que de R. Está mayor el hombre, pero sigue siendo un genio y un figura. Nunca ha sido mi jefe (no porque yo no quisiera) y no comparto ni una sola de las opiniones que tiene en la entrevista que le hacen pero hay que reconocer que no se ha equivocado mucho en 40 años porque es una de las fortunas más importantes del mundo. Así que le tendré en cuenta, al fin y al cabo llevo 10 años diciento que el futuro pasa por R y empiezo a cansarme, me estoy haciendo más dinosaurio día a día.

Trucos SAS. Más usos de INFILE y PIPE directorios en tablas SAS

Puede interesarnos tener directorios y subdirectorios en tablas SAS. Es decir, tabular el resultado de un lm en Unix o poner en una tabla el resultado de un dir de MS DOS / Windows. Ya tengo ejemplos publicados a este respecto:

Pero no está mal volver a poner un truco para analizar las posibilidades del INFILE + PIPE. Vamos a hacer un DIR de todo nuestro C:\ y sacar los archivos de mayor tamaño.

Árboles de decisión con SAS Base (con R por supuesto)

Con SAS Base podemos hacer árboles de decisión porque tenemos R. Así de sencillo. Vamos a utilizar SAS para gestionar nuestros datos y R será la herramienta que utilicemos para la realización del modelo de árbol de decisión. Posteriormente emplearemos las reglas generadas por el modelo para etiquetar a nuestros clientes en SAS. Con esta entrada pretendo ilustrar una serie de ejemplos en los que comunico SAS con R. Una herramienta nos sirve para el tratamiento de datos y la otra la utilizaremos para realizar modelos que no están al alcance de SAS. Para realizar esta comunicación SAS-R os planteo la creación en SAS de ficheros de texto con las instrucciones en R y la ejecución en modo batch de R con ese código creado en SAS. Aquí tenéis punto por punto el ejemplo:

Trucos SAS. La ventana LOG vacía o limpia

Duda que me trasmitieron hace tiempo. Necesito que no se genere salida en el log porque se llena y mi proceso da problemas. Con el PROC PRINTTO podemos hacer que nuestros procesos no generen salida en la ventana log. Para ello sólo tenemos que utilizar el siguiente código:

proc printto log='null'; quit;

Si deseamos volver a tener resultados en la ventana log sólo tenemos que hacer:

proc printto log=log; quit;

Con el PROC PRINTTO no sólo podemos dirigir el log a un fichero, también podemos dirigir el OUTPUT con la opción PRINT. Tenéis muchos ejemplos en la red acerca de este tema. Para limpiar el log también podemos emplear la instrucción DM:

Trucos R. Llevar a SAS las reglas de un árbol de decisión

Vuelvo hoy con el uso de rpart para la creación de árboles de decisión con R. Pero hoy, además de realizar un modelo de árbol con R quiero presentaros una función que nos permite guardar las reglas generadas con nuestro modelo en un fichero de texto para su posterior utilización con SAS. Retomamos un ejemplo visto con anterioridad en la bitácora con ligeras modificaciones:

#Inventamos un objeto para realizar el modelo

#En una cartera de clientes nuestro modelo tiene que identificar

#cuales contratan un PVI

#

clientes=20000

saldo_vista=runif(clientes,0,1)*10000

saldo_ppi=(runif(clientes,0.1,0.2)*rpois(clientes,1))*100000

saldo_fondos=(runif(clientes,0.1,0.9)*(rpois(clientes,1)-1>0))*100000

edad=rpois(clientes,60)

datos_ini<-data.frame(cbind(saldo_vista,saldo_ppi,saldo_fondos,edad))

datos_inisaldo_ppi=(edad<=68)*datos_inisaldo_ppi

#Creamos la variable objetivo a partir de un potencial

datos_inipotencial=runif(1,0,1)+

(log(edad)/(log(68))/100) +

runif(1,0,0.001)*(saldo_vista>5000)+

runif(1,0,0.001)*(saldo_fondos>10000)+

runif(1,0,0.007)*(saldo_ppi>10000)-

runif(1,0,0.2)

datos_inipvi=as.factor((datos_inipotencial>=quantile(datos_inipotencial,

0.90))*1)

#

#Empleamos rpart para la realización del modelo

#

library(rpart)

arbol=rpart(as.factor(pvi)~edad+saldo_ppi+saldo_fondos,

data=datos_ini,method="anova",

control=rpart.control(minsplit=30, cp=0.0008) )

Tenemos un objeto rpart llamado arbol. En este punto necesitamos disponer de las reglas generadas por el modelo para SAS, donde el módulo específico para poder realizar determinados modelos tiene un precio muy alto. Buscando en Google encontraremos este link. En él tenemos una genial función de R list.rules.rpart que nos permite identificar las reglas que ha generado el modelo. Modificamos ligeramente esta función para que nos sirva en nuestros propósitos:

Macros (fáciles) de SAS. Días de un mes en una fecha

Macro de SAS fácil y rápida que nos permite saber el número de días que tiene el mes de una fecha de SAS. La tenía para la automatización de un código que con una media y daba guerra cuando se trataba de un año bisiesto. 3 líneas de código:

%macro dias(fec);

((&fec-day(&fec)+1)+31-day((&fec-day(&fec)+1)+31))-(&fec-day(&fec))

%mend;

El razonamiento es sencillo. Se trata de poner a día 1 la fecha que le pasamos, irnos un mes después y hacer la diferencia. Por supuesto copiáis y pegáis el ejemplo en el editor:

Macros (fáciles) de SAS. Eliminar outliers en una variable

Hace tiempo ya os propuse una chapuza para eliminar outliers de forma multivariante. Por supuesto quedabaeliminar outliers en una variable. Recortar los valores extremos en aquellas variables cuantitativas que deseemos. Para ello os propongo una macro que no considero muy compleja y que os analizaré con mayor detalle, pero lo primero la macro al completo:

%macro elimina_outliers(

varib,  /*VARIABLE PARA ELIMINAR EL OUTLIER*/

entrada,/*DATASET DE ENTRADA*/

salida, /*DATASET DE SALIDA, PUEDE SER EL MISMO DE ENTRADA*/

corte_inferior, /*% DE CORTE INFERIOR*/

corte_superior);/*% DE CORTE SUPERIOR*/

*******************************************************************;

*CREAMOS LOS PERCENTILES;

data _null_;

call symput ("lim1",compress(0+&corte_inferior.));

call symput ("lim2",compress(100-&corte_superior.));

run;

*PREPARAMOS MV CON LOS NOMBRES QUE OBTENDREMOS DEL PROC UNIVARIATE;

data _null_;

call symput ('nom_lim1',compress("P_"||tranwrd("&lim1.",'.','_')));

call symput ('nom_lim2',compress("P_"||tranwrd("&lim2.",'.','_')));

run;

*EL UNIVARIATE GENERA UNA SALIDA SOLO CON LOS PERCENTILES DESEADOS;

proc univariate data=&entrada. noprint;

var &varib.;

output out=sal pctlpre=P_ pctlpts=&lim1.,&lim2.;

quit;

*CREAMOS MV CON LOS CORTES DESEADOS;

data _null_;

set sal;

call symput("inf",&nom_lim1.);

call symput("sup",&nom_lim2.);

run;

*REALIZAMOS EL FILTRO;

data &salida.;

set &entrada.;

if &varib.>&inf. and &varib.<&sup.;

run;

proc delete data=sal;run;

%mend;

Su ejemplo de uso correspondiente:

Los 10 errores y warnings más habituales en SAS

En función de los contactos con SAS support han elaborado un ranking de errores y warnings reportados a SAS con respecto al paso DATA. En este enlace tenéis el ranking, a los comentarios de Kim Wilson podéis añadir los míos. Veamos uno por uno esos errores:

  1. ERROR: AN INTERNAL ERROR HAS OCCURRED WHILE READING A COMPRESSED FILE. PLEASE CALL YOUR SAS SITE REPRESENTATIVE AND REPORT THE FOLLOWING…
    Tenéis que reparar el dataset como indica Kim, pero mucho ojo con mover datasets entre servidores o con trabajar con distintas versiones de SAS.
  2. ERROR: ARRAY SUBSCRIPT OUT OF RANGE AT LINE N AND COLUMN N
    Nos hemos ido de rango en el array sucede cuando recorremos los arrays con un bucle DO y el índice del bucle es mayor que el tamaño del array. Para evitarnos líos podemos hacer ARRAY AR(*) ; DO i = 1 TO DIM(AR); Que no se lleve nadie las manos a la cabeza.
  3. ERROR: THE FORMAT $NAME WAS NOT FOUND OR COULD NOT BE LOADED
    Llamamos a un formato que no existe, muy habitual en input o put.
  4. NOTE: THE MEANING OF AN IDENTIFIER AFTER A QUOTED STRING MAY CHANGE IN A FUTURE SAS RELEASE. INSERTING WHITE SPACE BETWEEN A QUOTED STRING AND THE SUCCEEDING IDENTIFIER IS RECOMMENDED.
    Esto no pasa…
  5. NOTE: INVALID ARGUMENT TO FUNCTION INPUT AT LINE N COLUMN N
    En ocasiones el formato que ponemos en input es incorrecto y se produce este error, habitual cuando trabajamos con fechas
  6. NOTE: MERGE STATEMENT HAS MORE THAN ONE DATA SET WITH REPEATS OF BY VALUES
    Cuando hacemos un merge si uno de los conjuntos de datos tiene observaciones duplicadas por la variable que ponemos en BY obtenemos este WARNING, cuando cruzamos tablas SAS hemos de tener mucho cuidado con las observaciones duplicadas.
  7. NOTE: SAS WENT TO A NEW LINE WHEN INPUT STATEMENT REACHED PAST THE END OF A LINE
    No es muy habitual este error. Tenemos que realizar lo que nos dice Kim. La opción FLOWOVER no la he empleado nunca, en este link tenéis ejemplos de esta problemática.
  8. NOTE: INVALID DATA FOR VARIABLE-NAME AT LINE N
    Si definimos una variable de un tipo no podemos emplear datos de otro tipo, es decir, si la variable es numérica no la igualéis a un caracter y viceversa. Tenedlo en cuenta.
  9. WARNING: THE QUOTED STRING CURRENTLY BEING PROCESSED HAS BECOME MORE THAN 262 CHARACTERS LONG. YOU MAY HAVE UNBALANCED QUOTATION MARKS.
    Otro problema poco habitual, seguid haciendo caso a Kim.
  10. WARNING: MULTIPLE LENGTHS WERE SPECIFIED FOR THE VARAIBLE VARIABLE-NAME BY INPUT DATA SET(S). THIS MAY CAUSE TRUNCATION OF DATA.
    Este warning es muy típico cuando realizamos merge con variables alfanuméricas. Imaginemos que un dataset tiene la variable póliza definida como 10. y otro tiene la variable póliza definida como12. si realizamos un merge por esa variable obtendremos este WARNING.

Estos son los errores que más aparecen en SAS SUPPORT. En mi opinión hay algunos que no son habituales pero hay algunos que son dudas recurrentes que me llegan. Al final lo que siempre plantea problemas son los formatos y las fechas en SAS, el 80% de las dudas que me llegan van por ahí. Espero complementar el mensaje de SAS.

Lectura de ficheros SAS7BDAT de SAS directamente con R

Un post de BIOSTATMATT que nos conduce a un código en R que nos permite leer datasets de SAS directamente con R sin necesidad de tener SAS. Un problema recurrente que abordaré con más detenimiento otro día [ahora me voy a pescar]. Aquí tenéis el enlace:

http://biostatmatt.com/archives/1216

Sólo tenéis que cargar la funciónread.sas7bdat que tenéis en este enlace. Y ya podéis leer conjuntos de datos SAS. Ejemplo:

source("http://biostatmatt.com/R/sas7bdat.R")

datos = read.sas7bdat("D:\\raul\\Trabajo\\salida\\p03.sas7bdat")

De momento lo he probado en conjuntos de datos SAS sin índices y sin comprimir, si encuentro algún problema primero se lo reporto a la gente que ha creado esta función y más tarde os lo comento.

Trucos SAS. Validación de consultas con PROC SQL

Hay ocasiones en las que lanzamos consultas a las BBDD con SAS y necesitamos saber si son correctas. Quería plantearos un truco SAS para PROC SQL que valida las consultas antes de ser ejecutadas. Empiezo el truco en la línea habitual, creo un dataset de ejemplo y os presento como realizar la validación, de este modo vosotros podéis copiar y pegar el código en una sesión de SAS y comprobar su funcionamiento. Datos aleatorios de partida:

Curso de lenguaje SAS con WPS. Librerías en WPS

Sobre el trabajo con librerías en SAS se pueden escribir libros. Todas las personas que han aprendido SAS conmigo a lo largo de los años han oído el mismo duscurso. «Hay que tener mucho cuidado con las librerías en SAS. Tenemos que tener muy claro que tablas son temporales, cuales han de ser permanentes. El problema del trabajo con SAS reside en el espacio en disco». Ya son decenas las personas que ahora hacen lo que pueden con SAS que han escuchado estas palabras y que siguen llenando discos y más discos incluso de los servidores con SAS más potentes de España.

Macros (fáciles) de SAS. Determinar si existe una variable en un dataset

Duda que me plantearon el otro día. ¿Es posible determinar si existe una variable en un conjunto de datos SAS? Pretendían crear una macro variable que tomara el valor 1 si existía o 0 si no existía. Resolví la duda pero me guardé la macro para ponerla en el blog y así la podéis utilizar todos. De eso se trata, de compartir mis conocimientos con todos de forma altruista por ello prefiero que planteéis las dudas en el blog, no por correo. Así, entre todos, las podemos resolver. En este caso la macro es muy sencilla y tiene pocas líneas:

El debate político o como analizar textos con WPS

¿Qué hacen los políticos españoles en el Congreso de los Diputados? Las tertulias radiofónicas están llenas de analístas políticos que podrán opinar sobre la labor del Congreso mejor que yo. Sin embargo yo tengo WPS, sé programar en SAS y en la web del Congreso están todas las sesiones y todas las intervenciones de la democracia. Pues con estos elementos vamos a iniciar un proceso de text mining, aunque no llegaremos a realizar ningún análisis complejo. Para comenzar, como siempre, necesito datos. Me he guardado la sesión del Congreso de los Diputados del día 26/01/2011 como web y posteriormente con Word la he salvado como fichero de texto (ojo con las codificaciones). De todos modos podéis descargaros aquí el fichero.