/head>

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.

13 pensiamientos en “Trucos SAS. Primer y último elemento de un array

  • Rodrigo

    Una pequeña corrección en tu código, Raíl. Parece que la variable num te calcula el número de columnas entre la primera informada y la última no nula. Para calcular el número de elementos no nulos del array sería:


    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);
    i=dim(m);
    end;
    end;
    /*ULTIMO ELEMENTO*/
    do i = dim(m) to 1 by -1;
    if m(i) ne . then do;
    ultimo=m(i);
    i=1;
    end;
    end;
    /*NUMERO DE NO NULOS*/
    do i = 1 to dim(m);
    if m(i) ne . then do;
    num=num+1;
    end;
    end;
    drop i;
    run;

    Responder
  • rvaquerizo

    Tienes toda la razón. En realidad este código sirve para hacer una media con valores perdidos.

    Responder
  • Dolores

    Buenas tardes Raúl,

    Tengo una duda, por si puedieras ayudarme,en macros estoy muy pegada… tengo una macro que he heredado que tengo que ejecutar 12 veces desde el cierre del año anterior, por ejemplo 201106 hasta el actual 201204 y el paso data que he generado funciona pero no se llamarla bien dentro… ¿podrías ayudarme?

    Gracias de antemano por la ayuda.

    Este es el código:

    /*En esta paso generaremos 12 meses de medias mensuales, desde el cierre anterior del mes actual hasta el cierre actual*/
    /*genera 12 medias mensuales*/
    data _null_;
    *generamos año y mes;
    anyo=int(&periodo_ini./100);
    mes= &periodo_ini. – anyo*100;

    *genera 12 meses;
    do a=1 to 12;
    mes=mes+1;
    if mes >12 then do;
    anyo=anyo+1;
    mes=1;
    end;
    periodo=anyo*100+mes;

    *genera 12 medias mensuales, AQUI FALLA!;
    %medias_mensuales(&periodos);

    end;
    run;

    Saludos cordiales.

    Responder
  • rvaquerizo

    Mirate esta entrada:

    http://analisisydecision.es/trucos-sas-operar-con-fechas-yyyymm-tipicas-de-particiones-oracle/

    Creo que hay una macro que te puede ayudar.

    Responder
  • Dolores

    Buenas tardes Raúl,

    Te escribo un poco tarde porque no daba con la tecla… hata hoy!! que por fin lo he logrado!!! eso sí, con tu ayuda ;)

    Muchas gracias por tu rapidez en contestarme y por tu amabilidad.

    Saludos.

    Responder
  • Mamen

    Hola Raúl,
    Tengo una duda muy relacionada con este tema y la verdad es que con el SAS me manejo pero no llego al nivel de macros y bucles…
    Estoy trabajando en una tabla con clientes que tienen diferentes ingresos realizados en una fecha distinta.
    Lo que no se muy bien es como hacer un bucle que me marque, para cada cliente, cual ha sido el primer ingreso, el segundo, el tercero…esto es, que me indique el orden de cada ingreso para el cliente según la fecha.
    Ahora mismo lo estoy haciendo generando tablas complementarias a partir de la máxima fecha y asi voy marcando a cada cliente pero imagino que con una macro el proceso sería mucho mas sencillo…me podrías ayudar???
    Muchisimas gracias!!
    Un saludo

    Responder
  • rvaquerizo

    Hola, ¿tienes los datos en filas? Si es así leete esto:

    http://analisisydecision.es/monografico-datos-agrupados-en-sas/

    Si los datos los tienes en columna tendrías que utilizar arrays.

    Responder
  • Nacho

    Mamen,

    qué estructura tiene tu tabla? Tres columnas? (Cliente, ingreso, fecha)? A ver si te puedo ayudar.

    Un saludo,
    Nacho.

    Responder
  • Isaías

    Os dejo una versión modificada del programa en el que se realiza todo en una sóla iteración.

    Primer elemento, último y recuento de no nulos.

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

    Responder
    • Enrrique

      Amigo me puedes ayudar a entender la lógica de tu código, no entiendo como es que toma el ultimo valor.

      Saludos

      Responder
  • Rodrigo

    Estimado,
    necesito su ayuda urgente
    resulta que tengo unos datos de esta forma

    Campo1 campo2
    2002 10
    2343 .
    2152 .
    1234 8
    2131 .

    Necesito ir recorriendo el campo 2 y agregar el numero anterior no nulo(10) hasta que aparezca otro numero en el campo no nulo(8), es decir dejarla así.
    (campos insertados con el codigo)
    Campo1 campo2
    2002 10
    2343 (10)
    2152 (10)
    1234 8
    2131 (8)

    Favor tu ayuda

    Gracias

    Responder
  • rvaquerizo

    Hola Rodrigo,

    Necesitas usar retain como una sentencia dentro de un paso DATA:

    data datos;
    input Campo1 campo2;
    datalines;
    2002 10
    2343 .
    2152 .
    1234 8
    2131 .
    ;run;

    data datos;
    set datos;
    retain suma 0;
    suma = sum(suma,campo2);
    run;

    Saludos.

    Responder
  • Rodrigo

    Pero me suma el campo 2 anterior con el nuevo no nulo, no va cambiando ni reemplazando

    Responder

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *