miércoles, 23 de abril de 2014

Procedimientos de agregación en SAS (proc sql, proc summary y proc means)

En el siguiente post mostramos con ejemplos los diferentes métodos de agregación de los que disponemos en el módulo BASE de SAS. Se incluye un script con ejemplos utilizando el procedimientos generalista 'proc sql' o bien procedimientos propios de agregación como 'proc means' o 'proc summary'


Agregados en SAS

En primer lugar mostramos el mismo agregado realizado en vía proc sql y vía proc summary o proc means:

proc sql:
proc sql;
create table agregado as
(select dimension1, dimension2, sum(indicador1), avg(indicador2), max(indicador3)
from detalle
group by dimension1, dimension2);
quit;

proc summary:
proc summary data=detalle nway;
   class dimension1 dimension2;
   var indicador1 indicador2 indicador3;
   output out=agregado(drop=_type_ _freq_)
   sum=indicador1 ;
run;

proc means:
proc means data=detalle noprint nway;
   class dimension1 dimension2;
   var indicador1 indicador2 indicador3;;
   output out=agregado(drop=_type_ _freq_)
   sum(indicador1) = suma_indicador1 mean(indicador2) = media_ indicador2 max(indicador3) = max_indicador3 ;
run;

Un resumen de equivalencias sería:
  


Funcionalidad

Procedimiento agregación

Proc sql

Tabla entrada

data=tabla_detalle

from tabla_detalle

Tabla salida

output out =tabla_agregado

create table tabla_agregado as

Indicadores de análisis

var indicador1 indicador2 …

Select sum(indicador1), mean(indicador2), ..

Variables de agregación

class indicador1, indicador2,…

group by dimension1, dimension2, …

Estadísticas a obtener

Especificadas en el procedimiento agregación

Especificadas en el proc sql

En los procedimientos de agregación tenemos la opción de dar la salida a último nivel de agregación o mostrando todos los niveles. Para quedarnos con el últimos nivel de agregación en base a la clave definida añadimos la claúsula nway. La clave de agregación queda definida en la claúsula class y en el output  indicamos la tabla de salida. Utilizamos la claúsula drop para eliminar las variables internas que genera el procedimiento y no queremos mostrar en la salida.  Finalmente definimos los valores estadísticos a obtener que en el caso del ejemplo son sum, mean y max y las variables donde los alojamos.  Ambos procedimientos dan la opción de obtener otros muchos valores estadísticos tales como:  rango (range), varianza(var), desviación estándar(stddev), etc..

En el procedimiento proc means se añade la claúsula noprint ya que por defecto da la salida en el output de SAS.  La principal diferencia entre proc summary y proc means es ésta de la salida y que proc means por defecto calcula valores estadísticos para todas las variables numéricas aunque no sean detalladas explícitamente en la salida.

Existen notables diferencias entre el uso e proc sql o de un procedimiento de agregación, siendo quizás la principal que el procedimiento de agregación obtiene agregados a todos los niveles y combinaciones posibles para las variables definidas en la clave, pudiendo manejar el nivel que queramos utilizando la variable interna _type_.
A continuación se incluye un script en el que partiendo de una tabla de detalle que se construye en el propio script de obtienen agregados a diferentes niveles utilizando tanto proc summary como proc means.

data ventas(drop = i j);
length oficina $100.;
oficina = 'Madrid';
do i = 1 to 10;
vendedor = compress('m_vendedor'||i);
       do j = 1 to 20;
       producto = compress('P'||j);
       unidades = round(ranuni(1)*20);
       output;
       end;
end;
oficina = 'Barcelona';
do i = 1 to 10;
vendedor = compress('b_vendedor'||i);
       do j = 1 to 20;
       producto = compress('P'||j);
       unidades = round(ranuni(1)*20);
       output;
       end;
end;
oficina = 'Valencia';
do i = 1 to 10;
vendedor = compress('v_vendedor'||i);
       do j = 1 to 20;
       producto = compress('P'||j);
       unidades = round(ranuni(1)*20);
       output;
       end;
end;
oficina = 'Lisboa';
do i = 1 to 10;
vendedor = compress('l_vendedor'||i);
       do j = 1 to 20;
       producto = compress('P'||j);
       unidades = round(ranuni(1)*20);
       output;
       end;
end;
run;


/* Agregado empleando proc sql */
/* Nivel.1 */
/* Agregado a nivel de variable oficina */
proc sql;
create table ag1_oficina as (
select oficina, sum(unidades) as sum1
from ventas
group by oficina);
quit;

proc summary data=ventas  NWAY ;
class oficina;
var unidades;
output out=ag1_oficina(drop = _type_ _freq_ ) sum = unidades;
run;

/* Agregado a nivel de variable vendedor */
proc sql;
create table ag1_vendedor as (
select vendedor, sum(unidades) as sum1
from ventas
group by vendedor);
quit;

proc summary data=ventas  NWAY ;
class vendedor;
var unidades;
output out=ag1_vendedor(drop = _type_ _freq_ ) sum = unidades;
run;

/* Agregado a nivel de variable producto */
proc sql;
create table ag1_producto as (
select producto, sum(unidades) as sum1
from ventas
group by producto);
quit;

proc summary data=ventas  NWAY ;
class producto;
var unidades;
output out=ag1_producto(drop = _type_ _freq_ ) sum = unidades;
run;

/* Nivel.2 */
/* Agregado a nivel de variables oficina y vendedor */
proc sql;
create table ag2_ofi_vend as (
select oficina, vendedor, sum(unidades) as sum2
from ventas
group by oficina, vendedor);
quit;

proc summary data=ventas  NWAY ;
class oficina vendedor;
var unidades;
output out=ag2_ofi_vend(drop = _type_ _freq_ ) sum = unidades;
run;

/* Agregado a nivel de variables oficina y producto */
proc sql;
create table ag2_ofi_prod as (
select oficina, producto, sum(unidades) as sum2
from ventas
group by oficina, producto);
quit;

proc summary data=ventas  NWAY ;
class oficina producto;
var unidades;
output out=ag2_ofi_prod(drop = _type_ _freq_ ) sum = unidades;
run;

/* Nivel.3 */
/* Agregado a nivel de variables oficina, vendedor y producto */
proc sql;
create table ag3_ofi_vend_prod as (
select oficina, vendedor, producto, sum(unidades) as sum3
from ventas
group by oficina, vendedor, producto);
quit;

proc summary data=ventas  NWAY ;
class oficina vendedor producto;
var unidades;
output out=ag3_ofi_vend_prod(drop = _type_ _freq_ ) sum = unidades;
run;

/* Empleamos proc summary para obtener todos los niveles de agregación y después
filtramos. Para obtener todos los niveles elimnamos clausul NWAY y controlamos en la
salida el nivel con la variable de sistema _type_ */
proc summary data=ventas ;
class oficina vendedor producto;
var unidades;
output out=ag_total(drop = _freq_ ) sum = unidades;
run;

/* A partir del agregado total y conociendo el valor de la variable _type_ para los diferentes
niveles, podemos sacar agregados a distintos niveles.
Por ejemplo, para obtener el agregado total por oficina, el agregado por oficina_vendedor
y el agregado a más bajo nivel sería */
data ag1_oficina (keep = oficina unidades)
ag2_ofi_vend (keep = oficina vendedor unidades)
ag3_ofi_vend_prod (keep = oficina vendedor producto unidades);
set ag_total;
if _type_ = 4 then output ag1_oficina;
if _type_ = 6 then output ag2_ofi_vend;
if _type_ = 7 then output ag3_ofi_vend_prod;
run;
  
/* Obtenemos el proc means equivalente al proc summary obtenido para el agregado
a más bajo nivel */
proc summary data=ventas  NWAY ;
class oficina vendedor producto;
var unidades;
output out=ag3_ofi_vend_prod(drop = _type_ _freq_ ) sum = unidades;
run;

proc means data=ventas noprint nway;
   class oficina vendedor  producto ;
   output out=ag3_ofi_vend_prod(drop=_type_ _freq_) sum = unidades ;
run;

No hay comentarios:

Publicar un comentario