Archivo de la etiqueta: array

Máximo por registro de una serie de variables carácter en SAS

Un lector del blog preguntaba como obtener el valor máximo dentro de un registro, por fila, de una sucesión de variables caracter; evidentemente la función max no servía porque es específica para variables numéricas. La duda la planteaba del siguiente modo:

Pero tengo una duda que no soy capaz de sacar y no veo ninguna cosa parecida para poder sacarlo, a ver si me puedes ayudar, o si no, pues me dices que no y no hay ningún problema.

Tengo un data de este estilo:
Nombre    Clave1    Clave2    Clave3
Ana             A            A            B
Pepe           H            M            C
Juan           A             A            A

El tema es que necesito calcular el máximo de todas las claves para cada persona, es decir,
Nombre    Clave1    Clave2    Clave3    Max
Ana             A            A            B         B
Pepe           H            M            C        M
Juan           A             A            A         A

Como son letras, no me funciona el max en el proc sql y tampoco sé ninguna función que pueda pasarme las letras a numéricas.
Está claro que la única manera que se me ocurre es transformando las letras a números con un case, hacer el máximo y después transformarlo otra vez a letras, pero es por si sabes alguna manera mejor de hacerlo.

La solución que le planteo se realiza con un array donde seleccionamos sólo las variables clave:

Data datos;
input Nombre $ Clave1 $ Clave2 $ Clave3 $;
datalines;
Ana A A B
Pepe H M C
Juan A A A
;run;

data datos;
set datos;
array cl (*) clave:;
maximo=cl(1);
do i=1 to dim(cl);
if cl(i)>maximo then maximo=cl(i);
end;
drop i;
run;

Inicializamos el máximo al primer elemento del array y vamos recorriendo las variables, si una es mayor que la otra se modifica el máximo. Espero que le sirva a algún otro lector. Saludos.

Trucos SAS. Lista de variables missing

Duda que me plantearon ayer por la tarde. Dada una serie de variables determinar que registro tiene todas esas variables nulas. El truco que planteo puede servir para determinar incluso cuantos valores perdidos tiene esa lista de variables, ese truco me le reservo para otro día. El código lo acompaño con un ejemplo para que se pueda ejecutar y analizar su funcionamiento:

data aleatorio;
do i=1 to 20000;
aleat1=sqrt(rannor(45));
aleat2=sqrt(rannor(5));
aleat3=sqrt(rannor(4));
aleat4=sqrt(rannor(450));
aleat5=sqrt(rannor(40));
output;
end;
run;

data fila_nula;
set aleatorio;
nulo=0;
array varib(*) aleat1--aleat5;
do j=1 to dim(varib);
if not missing(varib(j)) then nulo=i;
end;
drop j;
if nulo=0;
run;

Muy sencillo el truco. Si se encuentra alguna variable que no es nula la variable nulo ya no toma valor 0. Espero que os sea de utilidad. Saludos.

Trucos SAS. Primer y último elemento de un array

Breve entrada sobre el uso de arrays en SAS. Dada una tabla SAS como esta con una variable mes1, mes2, … mesN:

arrays_sas.PNG

Necesitamos identificar el primer y el último elemento no nulo de un array y el número de elementos no nulos de ese array. Veamos el ejemplo:

data datos;
input id mes1 mes2 mes3 mes4 mes5 mes6;
datalines;
1 . . . . . .
2 162.18 88.41 919.62 891.25 837.73 163.14
3 . 790.52 160.03 . 60.31 343.30
4 . . 482.45 755.39 . .
5 265.17 963.53 . . 392.06 .
6 . 214.95 616.17 183.01 778.48 57.42
7 191.52 . 208.50 50.55 705.72 .
8 711.76 . . . 193.20 658.45
9 782.67 172.49 539.42 663.28 4.53 358.51
10 695.12 367.74 . 573.47 366.30 951.98
;
run;

Para este proceso creamos un array que recorreremos 2 veces, una hacia delante para identificar el primer elemento y otra a hacia atrás para identificar el último elemento:

data datos;
set datos;
array m(*) mes:;
*PRIMER ELEMENTO;
num=0;
do i = 1 to dim(m);
if m(i) ne . then do;
  primero=m(i);
  num=i;
  i=dim(m);
end;
end;
*ULTIMO ELEMENTO;
do i = dim(m) to 1 by -1;
if m(i) ne . then do;
  ultimo=m(i);
  num=i-num;
  i=1;
end;
end;
drop i;
num=num+1;
run;

Como hemos indicado el array se recorre dos veces, la primera vez de forma ascendente para buscar el primer elemento y la segunda de forma descendente para encontrar el último, la diferencia más uno es el número de elementos no nulos que tiene ese array. Ejemplo de uso de arrays en SAS. Saludos.

Trucos SAS. Operaciones con tablas de dimensiones con SAS

Algunos llaman a las tablas de dimensiones tablas de lookup, yo me niego. Con SAS ya hemos visto como crear cruces de tablas de dimensiones con tablas de hechos a través de formatos, bajo mi punto de vista el método más eficiente. Pero hoy quería traeros un ejemplo de cruce de tabla pequeña con tabla grande a través de arrays multidimensionales con SAS. Se trata de guardar los valores de la tabla “pequeña” en un array temporal multidimensional cuando leemos la tabla grande. Para ilustrar esta tarea he preparado un ejemplo:


data aleatorio;
do i =1 to 2000;
grupo = round(1+3*ranuni(4));
importe=ranuni(34)*grupo*1000;
output; end;
run;
proc summary data=aleatorio nway;
class grupo;
output out=medias (keep=grupo importe) mean(importe)=;
quit;

Generamos un conjunto de datos SAS aleatorio con una variable grupo y una variable importe, calculamos la media del importe por grupo y deseamos medir registro a registro la diferencia con respecto a la media del grupo. Para estos casos podemos trabajar con formatos o, por ejemplo, con macro variables:


data _null_;
set medias;
if grupo = 1 then call symput('med1',importe);
if grupo = 2 then call symput('med2',importe);
if grupo = 3 then call symput('med3',importe);
if grupo = 4 then call symput('med4',importe);
run;
data aleatorio;
set aleatorio;
if grupo = 1 then dif = importe/&med1.-1;
if grupo = 2 then dif = importe/&med2.-1;
if grupo = 3 then dif = importe/&med3.-1;
if grupo = 4 then dif = importe/&med4.-1;
run;

Estoy de acuerdo en que este código se puede hacer más eficiente pero sigue siendo algo engorroso. Bien, hoy quería plantearos otra forma de hacerlo a través de arrays multidimensionales. Planteo el código, lo ejecutáis y comentamos:

data aleatorio;
array med(4,2) _temporary_;
if _n_ = 1 then do i=1 to 4;
set medias;
med(i,2) = importe;
end;
set aleatorio;
dif = importe/med(grupo,2)-1;
run;

Se trata de recorrer nuestra tabla de dimensiones, en este caso la tabla con las medias y meter su contenido en un array temporal de 2 dimensiones que denomino med, este array tiene 4 filas y 2 columnas, la dimensión de nuestra tabla de dimensiones. Posteriormente leo la tabla de hechos y empleo el campo grupo para seleccionar el elemento del array que deseo. Es un código sencillo de replicar sobre todo si nuestras variables índices (en este caso la variable grupo) son números, en otro caso el código se complica ligeramente pero sigue siendo sencillo de interpretar. Estoy seguro de que este truco SAS puede resultaros útil (sobre todo a algún pésimo jugador de golf). Saludos.