sas guide

Alterando Comprimento de Campo Novo no SAS

Muitas vezes no SAS precisamos criar novos campos. No entanto, é preciso saber lidar com o comprimento dos campos. Por exemplo, suponha que você tenha uma tabela com informações de vendas das suas lojas:

Leia mais…

Anúncios

Loop no SAS com Do + end

Uma pergunta que eu já ouvi bastante é: como fazer um loop no SAS? Essa pergunta vale para qualquer linguagem, é uma das coisas mais utilizadas e até agora não tinha escrito nada sobre o tema.

Leia mais…

Soma com condição no SAS: Agrupamentos com Proc Sql

O group by é um método bem tranquilo de agrupar os valores de uma coluna de acordo com os valores de outra coluna. Veja os três exemplos abaixo, onde queremos primeiro saber qual o número de vendas de cada marca, o número de vendas por estado e o número de vendas de cada marca em cada estado:

Leia mais…

Acompanhando a execução da macro no SAS

Mostrei no post Acompanhando o processo no SAS utilizando o Sysecho como utilizar o comando sysecho para acompanhar um procedimento extenso, algo que leva muito tempo para ser executado ou com muitas etapas. Porém, seria interessante também fazer um acompanhamento parecido quando executamos uma macro.

Leia mais…

Convertendo diferentes formatos de data no SAS

Essa é intuitiva, mas não sei se todo mundo conhece. Então, se você leu Como calcular a diferença entre duas datas no SAS? e Formatando Datas no SAS, agora que já conseguiu criar colunas e mudar formato numérico para data, pode ainda querer trocar aquela data 20DEC2016 para 20/12/2016. Isso pode ser feito com o format:
*codigo que pega a tabela_old, com o campo data no formato 20DEC2016;
*e cria uma tabela nova chamada tabela_new com a data no formato 20/12/2016;
data tabela_new;
	set tabela_old;
 	format data ddmmyy10.;
run;

SAS: Executando diversos códigos em um só com o include

Assim como é possível chamar outros códigos no R e utilizar algumas funções prontas, no SAS algo semelhante pode ser feito declarando INCLUDE.

Quando você utiliza o include seguido de um caminho com um programa SAS, o que vai acontecer é que esse programa será executado. Sendo assim, você pode rodar diversos códigos em um projeto só, pode consolidar as suas libnames em um lugar só, enfim, há várias alternativas, todas com o include.

Uma situação hipotética: sua empresa possui uma base padrão, dentro de um DW qualquer, com um campo de data no formato string “ddmmaaaa”. Vamos supor que você tenha criado um projeto no qual um dos programas seja uma macro, denominada trata_data, que recebe a base padrão e converte o campo string para o formato data padrão do SAS. Você utilizou essa macro nesse projeto, mas ela é pode ser útil em vários outros estudos. O que você pode fazer é salvar essa macro como um programa em um diretório e quando você precisar utilizá-la em outro código, você utilizará algo como a sintaxe:

*chama a macro que tratara a data da base padrao (base_in) 
*e gera uma base com campo tratado (base_out);
%include '/sasdata/minhaempresa/macro_trata_data.sas';
%trata_data(base_in, base_out);

Outra forma de utilizar o include é na automatização de alguns processos. Vamos supor que você tenha criado um modelo estatístico que gera o rating das empresas clientes do seu banco e você deseja automatizar o processo de geração de rating para várias bases diferentes que chegarão mensalmente. Para isso, você pode criar diversos programas que receberão algumas variáveis, como a base de entrada e uma base de cadastro que enriquecerá a base de entrada, e rodá-los todos com o include. O exemplo abaixo pressupõe um programa chamado gera_rating_empresa.sas e dentro desse programa você possui duas variáveis/bases que devem ser passadas pelo usuário chamadas base_in e base_endereco (lembre-se que no programa elas precisam ser chamadas com &base_in e &base_endereco):

*insira o nome da base de entrada com campo CNPJ com 14 dígitos (string);
%let base_in = base_entrada_yyyymmdd;

*passe a base que enriquecera com as informacoes de endereco;
%let base_endereco = base_endereco_yyyymmdd;

*execute o programa;
%include "/sasdata/.../gera_rating_empresa.sas";

Não se esqueça de ficar craque em macros / let: Macros e a expressão Let no SAS

Combinando três tabelas com o left join

Utilizando as informações do post Como combinar tabelas no SAS utilizando left join e full join, vamos imaginar que não tenhamos apenas duas tabelas, mas sim três, sendo que a terceira tabela contém as notas dos alunos que cursam Física:
turma_fis
Para montar uma única query que traga a nota de física, basta continuar o left join:
**** notas dos alunos de calculo incluindo as de fisica dos que fizeram ****;
proc sql;
    create table exemplo_left_join as
    select a.*, b.nota_estat, c.nota_fis
    from turma_calc as a
    left join (select * from turma_estat ) as b
      on a.nome = b.nome
    left join (select * from turma_fis) as c
      on a.nome= c.nome;
run;
combina_3_tabelas_1
E você poderia inclusive filtrar antes de aplicar o left join. Como?
Bem, para quem leu o post SQL dentro do SAS sobre SQL fica bem claro o que foi feito acima: foi aplicado um left join em uma base construída entre parênteses. Ou seja, se para extrair as informações da turma de Física usamos select * from turma_fis, pra extrair os alunos aprovados na disciplina bastaria utilizar select * from turma_fis where Nota_Fis >= 6, teríamos então:
**** excluindo os alunos reprovados em fisica ****;
proc sql;
    create table exemplo_left_join_2 as
    select a.*, b.nota_estat, c.nota_fis
    from turma_calc as a
    left join (select * from turma_estat ) as b
      on a.nome = b.nome
    left join (select * from turma_fis where Nota_Fis >= 6) as c
      on a.nome= c.nome;
run;
combina_3_tabelas_2
Agora que você sabe extrair informações utilizando o SQL e sabe que você pode fazer o que quiser dentro do parênteses antes de aplicar o left join, você poderia inclusive ser mais ousado e criar uma marcação de alunos aprovados, onde o campo Aprovado receberia 1 quando o aluno tem nota superior ou igual a 6 e 0 caso contrário:
**** cria uma flag = 1 para trazer quem foi aprovado em fisica e estatistica ****;
proc sql;
    create table exemplo_left_join_3 as
    select a.*, b.Aprovado_Estat, c.Aprovado_Fis
    from turma_calc as a
    left join (
            select *, case when Nota_Estat >= 6 then 1
            else 0 end as Aprovado_Estat from turma_estat ) as b
      on a.nome = b.nome
    left join (
             select *, case when Nota_Fis >= 6 then 1
             else 0 end as Aprovado_Fis from turma_fis) as c
      on a.nome= c.nome;
run;
combina_3_tabelas_3

Trabalhando com espaços e acentos no SAS

A pior coisa é utilizar campos com espaços em branco e acentos quando se está programando. Não é recomendável e muitas vezes resulta em erros. Porém, às vezes temos que lidar com isso porque alguém construiu uma base com campos dessa forma e não quer mudar.

No SAS é mais fácil lidar com isso, basta acrescentar aspas e a letra n. É bem semelhante quando você utiliza data, só que precisa trocar o ‘d’ por ‘n’.

Vamos supor que você receba os dados da turma de alunos do post Visualizando seus dados: histograma e queira criar uma marcação chamada Reprovação que receberá o número 1 para alunos que tiraram notas menor que 6, basta você criar o campo ‘Reprovação’n:

data dados_v2;
    set dados;
    if notas < 6 then 'Reprovação'n = 1;
    else 'Reprovação'n = 0;
run;

Poderíamos também cair em uma situação que seria necessário criar um campo Data de Atualização com a data do dia de hoje. Para isso, temos duas opções:

## primeira opcao:
data dados_v2;
    set dados;
    'Data de Atualização'n = today();
run;

## segunda opcao:
data dados_v2;
    set dados;
    'Data de Atualização'n = '13JUL2016'd;
run;

Contador e função oposta ao lag no SAS

Veja que exercício de lógica interessante:

Pense em uma base com clientes que possuem vários carros. Você tem linhas contendo o nome do cliente, o nome do carro que ele possui e a data de compra do veículo. Você precisa descobrir quais clientes possuem apenas um carro. A que eu vou demonstrar talvez não seja a mais eficiente, até porque eu precisei de alguns dados ao longo do estudo, como por exemplo qual a ordem em que o veículo foi comprado. Sem isso, não sei se eu teria pensado de outra forma. O legal da forma que foi feito o tratamento é que trabalha o raciocínio lógico e ainda apresenta alguns algoritmos úteis.

O passo a passo utilizado é o seguinte: ordene seus dados pelo nome e data de compra do veículo; crie um contador para representar se é o primeiro carro que aparece do cliente; crie uma coluna adicional para saber qual o contador da linha seguinte. Veja que se você tiver na linha 10 o valor 1 no contador, e na linha 11 você tiver o valor 2, é sinal de que o cliente possui pelo menos dois veículos. No entanto, se você tiver o valor 1 no contador da linha 10 e o valor 1 no contador da linha 11, o seu cliente da linha 10 possui apenas 1 carro.

Foi falado um pouco sobra a função lag() do SAS no post Média Móvel (Bônus: Código SAS e função lag). Ela simplesmente pega o valor da linha de cima da coluna que você quer. Por exemplo, se eu fizer lag(conta_carro), eu vou saber qual o valor da coluna conta_carro da linha anterior a que estou verificando. No caso apresentado nesse post, precisamos de uma função que faça o contrário da lag, ao invés de retornar o valor da linha anterior, deve retornar o valor da linha seguinte. Você verá que não existe uma função pronta para esse caso, mas o script é bem simples e se encontra na Parte 5 do código abaixo.

Veja o exemplo completo que você pode simular e acompanhar o passo a passo explicado acima:
**** Parte 1: Cria uma base de clientes ****;
data base_clientes;
    input nome $ carro $ DtCompra mmddyy8.;
    cards;
    Andre Onix 02/05/15
    Andre Palio 12/10/13
    Andre Uno 01/05/14
    Paulo Idea 10/06/15
    Jose Vectra 01/04/16
    Jose Eco 12/05/16 28
    Maria Corsa 10/25/14
    Maria Celta 02/01/16
    Renata Onix 02/09/12
    Renata Palio 06/05/11
    Renata Fit 02/11/16
    Renata Civic 05/22/14
    Michael Fit 07/13/15
    Bianca Clio 09/05/15
    Thais March 08/05/16
    Renan Palio 11/05/13
    Renan Gol 11/05/14
    ;
run;

**** Parte 2: Trata a variavel data ****;
data base_clientes_v2;
    set base_clientes;
    format DtCompra date9.;
run;

**** Parte 3: Ordena pelo nome do cliente e data da compra do veiculo ****;
proc sort data= base_clientes_v2; by nome DtCompra; run;

**** Parte 4: Cria um contador do numero de carros = conta qtas vezes o nome aparece****;
data base_clientes_v3;
    set base_clientes_v2;
    by nome;
    primeiro = first.nome;
    ultimo = last.nome;
    if primeiro = 1 then
    conta_carro = 1;
    else conta_carro+1;
run;

**** Parte 5: Cria uma coluna com o valor da linha seguinte da coluna conta_carro ****;
data base_clientes_v4;
    recno=_n_+1;
    set base_clientes_v3 end=last;
    if not last
    then set base_clientes_v3 (keep=conta_carro rename=(conta_carro=next_conta_carro)) point=recno;
    else call missing(next_conta_carro);
run;

**** Parte 6: Mantem apenas quem tem conta_carro = 1 e que a proxima linha eh 1 tb ****;
data clientes_com_um_carro;
    set base_clientes_v4;
    if conta_carro = 1 and next_conta_carro = 1;
run;