input

Formatação de Datas no SAS

Complementando o post Formatando Datas no SAS, aqui vão mais algumas dicas para formatar os campos de data no SAS.

Neste post aprenderemos como podemos criar um campo com o ano e o mês de uma data. Como um extra, lembraremos também como converter uma data no formato texto para um campo no formato data. E, por fim, um operador novo que acredito que não mencionei ainda que são as duas barras verticais ||, que servem para concatenar (=unir) dois campos.

Começamos com uma base que traz uma coluna com a data em formato de texto. A tabela abaixo tem as informações da data em que uma compra foi realizada e o valor gasto:

data compras;
    input dt_compra vlr_compras;
    cards;
 20151102 1000
 20151010 500
 20161201 650
 20140130 900
;
run;

post_formato_anomes

Agora, vamos converter a data que está em formato de texto e deixá-la em formato de data. Para isso, usamos a função input() combinada com o format. Chamaremos o campo novo de dt_compra_new. Apesar de ocupar mais espaço, é uma boa ideia para novos usuários do SAS criar campos novos, ao invés de perder os antigos, até mesmo para visualizar a diferença entre o campo novo e o antigo. A nossa tabela com o campo dt_compra_new se chamará formata_data:

data formata_data;
    set compras;
    dt_compra_new = input(put(dt_compra, 8.), yymmdd10.);
    format dt_compra_new yymmdd10.;
run;

post_formato_anomes_2

Agora, duas formas de obter um campo formado pelo ano e o mês da data em questão são mostrados abaixo. A primeira forma demonstrada abaixo é criando o campo ANO_MES_1. Obtemos esse campo extraindo o ano da data utilizando a função year() e o mês com a função month(). A partir desses dois valores, utilizamos as duas barras verticais ‘||‘ para juntá-los. Como o mês extraído corre o risco de ter um dígito apenas, precisamos acrescentar um zero para alguns casos (e.g.: o mês de setembro combinado com o ano 2018, se não colocarmos um zero no meio, ficaria 20183). A segunda maneira é utilizando a função put() combinada com o argumento monyy7. Veja o exemplo abaixo:

data formata_data_2;
    set formata_data;

    if month(dt_compra_new) < 10 then ANO_MES_1 = compress(year(dt_compra_new) || '0' || month(dt_compra_new));
    else ANO_MES_1 = compress(year(dt_compra_new) || month(dt_compra_new));

    ANO_MES_2 = put(dt_compra_new, monyy7.);

run;

post_formato_anomes_3

Teste os dois exemplos. Com eles você vai aprimorar mais ainda o uso do if, do || e da função put().

Bons estudos!

Anúncios

Como converter caractere para número no SAS

Complementando o post Tutorial: Trabalhando com Variáveis Texto no SAS, abaixo estão algumas formas de converter caractere para número no SAS. Primeiro, criamos um campo texto e na sequência demonstramos duas formas de convertê-lo em número. No primeiro exemplo temos um campo numérico escrito como texto que é convertido em em número com a função input() e o número de posições que o número terá. O segundo é um campo numérico com cifrão e o convertemos em número, sem incluir o cifrão.

Leia mais…

Conversão de Número para Texto no SAS

Já falei sobre como lidar com datas no SAS no post Formatando Datas no SAS e Como calcular a diferença entre duas datas no SAS?. Agora é hora de aprender como lidar com os formatos número e texto.
Utilizando os dados german_credit_2, primeiro criamos um campo chamado documento contendo alguns números aleatórios. Isso é algo comum de se encontrar por aí, conjuntos de dados nos quais o campo CPF ou RG está no formato numérico. Lidar com esses dados pode ser um problema, pois algumas vezes esse documento pode conter zeros na frente. Para solucionar esse problema, vamos converter o campo documento em formato numérico para um campo no formato texto  de três maneiras utilizando a função put(): colocando zeros na frente do número; sem colocar zeros e apenas passando o comprimento do campo; deixando o campo alinhado a esquerda, evitando espaços em branco que ficariam na opção padrão do SAS:
** Cria uma coluna com numeros de documento aleatorios;
data german_credit_21_v2;
     set tmp.german_credit_21;
     documento = round(rand("Uniform"),.000001)*1000000;
run;

** Converte a coluna documento para caracter;
data german_credit_21_v3;
     set german_credit_21_v2;

     *acrescenta zero;
     documento_zero = put(documento, z15.);

     *alinhado a direita por default;
     documento_str = put(documento, 15.);

     *alinha a esquerda;
     documento_teste = put(documento, 15. -L);
run;
Agora, pode ser que o contrário ocorra. Você queira converter do formato texto para o numérico. Novamente, apresentamos mais de uma opção. Podemos converter simplesmente multiplicando por 1, ou então podemos utilizar a função input() do SAS:
** Converte caractere para numerico;
data german_credit_21_v4;
     set german_credit_21_v3;
     
     *forma mais simples de fazer a conversao;
     documento_nr1 = documento_zero*1;

     *utilizando input;
     documento_nr2 = input(documento_zero, 15.);*escolhe comprimento;
run;
A  mesma função input() faz outros tipos de tratamento, considerando campos com vírgula e campos com $. Veja como vamos lidar com os dois campos criados abaixo (esse exemplo você pode aplicar em qualquer conjunto de dados que você possua em mãos):
data german_credit_21_v5;
     set german_credit_21_v4;
     texto_com_virgula = '5,500';
     numeric_var_comma = input(texto_com_virgula , comma5.);

     texto_com_cifrao = '$5,500';
     numero_dolar = input(texto_com_cifrao , dollar5.);
     format numero_dolar dollar10.;
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;

Formatando Datas no SAS

Muitas vezes você vai ter que lidar com datas no SAS que estão no formato numérico ou caractere. Vamos abordar algumas formas de converter um campo para o formato numérico.

Aqui nós vamos criar uma base de dados no SAS para fazer essas conversões:

data compras;
    input dt_compra vlr_compras;
    cards;
20151102 1000
20151010 500
20161201 650
20140130 900
;
run;

A tabela possui as datas das compras realizadas pelos clientes e os respectivos valores. Porém, ambas estão em formato numérico, conforme apontado pelo programa (item Columns):

exemplo_sas_data_1

Como eu faço então para converter uma coluna no formato numérico para o formato de data do SAS?

Para isto, você deve combinar o comando input() com o put – que faz conversão para texto antes – e o format. No exemplo abaixo, criei um campo novo com a data formatada (é aconselhável para quem está começando manter o antigo para não perder a informação e comparar):

data formata_data;
    set compras;
    dt_compra_new = input(put(dt_compra, 8.), yymmdd10.);
    format dt_compra_new yymmdd10.;
run;

E obtemos assim o seguinte resultado:

fomata_data

Como vocês podem ver, agora temos uma variável nova no formato de data. Isso facilita muito na hora de fazer análises e também cálculos envolvendo que envolvem este formato específico (e.g.: diferença de dias entre duas datas, pegar o mês do evento, etc.).

Em tempo, seria possível utilizar outros formatos de data seguindo o mesmo passo a passo. Por exemplo, yymmdd8.

Agora, vamos analisar o que aconteceria se tivéssemos uma situação em que a variável data estivesse em formato de texto:

/*Cria tabela exemplo*/
data compras;
     input dt_compra $ vlr_compras;
     cards;
 20151102 1000
 20151010 500
 20161201 650
 20140130 900
;
run;

exemplo_sas_data_3

Nesse caso, o que parece mais simples é repetir o feito anterior, porém excluindo o uso do put() (abaixo usando 8.):

data formata_data_2;
    set compras;
    dt_compra_new = input(dt_compra, yymmdd8.);
    format dt_compra_new yymmdd8.;
run;

Simples não?

BÔNUS 1: ENCONTRANDO A DATA MAIS RECENTE OU ANTIGA COM PROC SQL

Quando você precisar utilizar a função max() ou min() no proc sql, para obter a data mais recente ou antiga, tome cuidado para que seu output não saia bagunçado. Fique de olho na formatação do campo. Sempre que você utilizar a função max() ou a função min() no proc sql, não se esqueça de utilizar format. Exemplo:

proc sql;
select max(dt_compra_new) as maior_data format=date9.
      from formata_data_2;
run;

Dúvidas, sugestões ou críticas, basta comentar ou enviar um e-mail.

BÔNUS 2: FUNÇÕES PARA DATAS NO SAS

Algumas funções simples utilizadas no SAS, para encontrar o dia, o mês, o ano e o dia da semana, respectivamente, da data em questão:

data funcoes_datas;
    set formata_data;
    dia = day(dt_compra);
    mes = month(dt_compra);
    ano = year(dt_compra);
    dia_da_semana = weekday(dt_compra);
run;

Bons estudos!