Abordaremos tratamento de dados por meio do PROC SQL do SAS e o pacote dplyr do R.
O pacote dplyr do R foi escrito por Hadley Wickham, popular programador R que escreveu muitos pacotes úteis para o R, como ggplot2, tidyr etc.
O SAS não possui linha de comando. O código/script deve ser executado para retornar resultados.
R é uma linguagem de programação orientada a objetos. Os resultados de uma função são armazenados em um objeto e os resultados são extraídos do objeto, conforme necessário.
O SAS gira em torno da tabela de dados e usa procedimentos para criar e imprimir saída. Os resultados podem ser salvos em uma nova tabela de dados.
SAS | R |
---|---|
Compilador de script | Intérprete de linha de comando |
Principalmente orientado pela tabela de dados e procedimentos | Orientado a objeto |
Não é case sensitive | Case sensitive |
Definição | SAS | R |
---|---|---|
Exponenciação | ** | ^ |
Multiplicação | * | * |
Divisão | / | / |
Adição | + | + |
Subtração | - | - |
Definição | SAS (Mnemônico) | SAS (Símbolo) | R | Prioridade lógica |
---|---|---|---|---|
Igual | EQ | = | == | |
Não é igual | NL | ^= ¬= ~= | != | |
Maior | GT | > | > | |
Menor | LT | < | < | |
Maior ou igual | GE | >>= | >>= | |
Menor ou igual | LE | <= | <= | |
Igual a algum elemento de uma lista | IN | %in% | ||
Não | NOT | ^ ¬ ~ | ! | 1 |
E | AND | & | & | 2 |
OU | OR | | | | | 3 |
Definição | SAS | R |
---|---|---|
Máximo | max() | max() |
Mínimo | min() | min() |
Média | mean() | mean() |
Soma | sum() | sum() |
Contagem | count() | count() |
Tanto o PROC SQL do SAS quanto o pacote dplyr do R são poderosas ferramentas para tratamento de dados. A seguir tabela comparando algumas funções de dplyr a instruções SQL.
Descrição | Função dplyr | PROC SQL equivalente |
---|---|---|
Seleção de colunas (variáveis) | select() | SELECT |
Filtrar linhas (subconjunto) | filter() | WHERE |
Agrupar os dados | group_by() | GROUP BY |
Resumir (ou agregar) dados | summarise() | - |
Ordenar os dados | arrange() | ORDER BY |
Joining data frames (juntar tabelas) | join() | JOIN |
Criando Novas Variáveis | mutate() | COLUMN ALIAS |
Aqui veremos como selecionar dados de uma tabela.
Sintaxe para seleção:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM nome_tabela;
QUIT;
nome_tabela %>% select(coluna1, coluna2, ...)
Aqui, coluna1, coluna2, … são os nomes das colunas da tabela da qual desejamos selecionar os dados. Se quisermos selecionar todos os campos disponíveis na tabela, usamos a seguinte sintaxe:
PROC SQL;
SELECT *
FROM nome_tabela;
QUIT;
nome_tabela
Dentro de uma tabela é comum ocorrer valores duplicados, e muitas vezes desejamos listar apenas os valores diferentes (distintos).
Os codigos a seguir são utilizados para retonar apenas valores distintos (diferentes).
PROC SQL;
SELECT DISTINCT *
FROM nome_tabela ;
QUIT;
nome_tabela %>% distinct()
Utilizaremos a tabela CARS (mantendo apenas as linhas completas) presente no SAS Studio University para exemplificar a seleção de dados em uma tabela.
Os seguintes códigos selecionam as colunas “Make” e “Origin” da tabela “CARS”:
PROC SQL;
SELECT Make, Origin
FROM CARS;
QUIT;
CARS %>% select(Make, Origin)
Resultado:
Vejamos agora o resultado selecionando apenas os registros diferentes das colunas “Make” e “Origin” da tabela “CARS”:
PROC SQL;
SELECT DISTINCT Make, Origin
FROM CARS;
QUIT;
CARS %>% select(Make, Origin) %>% distinct()
Resultado:
Observamos uma redução no numero de registro de 428 para 38 devido a exclusão dos registros repetidos.
Extrair apenas os registros que atendem a uma condição especificada.
Códigos utilizados para filtrar registros:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM nome_tabela
WHERE condição;
QUIT;
nome_tabela %>%
select(coluna1, coluna2, ...) %>%
dplyr::filter(condição)
Em filter()
multiplos argumentos são equivalentes a utilizar &
.
Vamos selecionar as colunas Make, Origin e Cylinders, os registros distintos em que Origin é igual a ‘Europe’ e Cylinders igual a 4 ou 6:
PROC SQL;
SELECT DISTINCT Make, Origin, Cylinders
FROM CARS
WHERE Origin = 'Europe' AND Cylinders IN (4,6);
QUIT;
CARS %>%
select(Make, Origin, Cylinders) %>%
dplyr::filter(Origin == 'Europe', Cylinders %in% c(4,6)) %>%
distinct()
Resultado:
Observe que, neste caso, ao utilizar o R podemos fazer o filtro antes ou depois do select()
sem prejuízo do resultado. Porém quando utilizamos a função filter()
após o select()
devemos garantir que as colunas utilizadas no filtro estejam selecionas anteriormente.
Agora inserindo mais restrições. Vamos selecionar as colunas Make, Type e Origin, os registros distintos em que Origin é igual a Europe e Type diferente de SUV ou que Cylinders maior que 4:
PROC SQL;
SELECT DISTINCT Make, Type, Origin
FROM CARS
WHERE Origin = 'Europe' AND Type ^= 'SUV' OR Cylinders > 6;
QUIT;
CARS %>%
dplyr::filter(Origin == 'Europe', Type != 'SUV' | Cylinders > 6) %>%
select(Make, Type, Origin) %>%
distinct()
Ou
CARS %>%
select(Make, Type, Origin, Cylinders) %>%
dplyr::filter(Origin == 'Europe' & Type != 'SUV' | Cylinders > 6) %>%
select(-Cylinders) %>%
distinct()
Resultado:
Muitas vezes desejamos classificar os registros do conjunto de dados de acordo com uma ou mais colunas. Para ordernar o conjunto de dados em ordem crescente ou decrescente utilizamos:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM nome_tabela
ORDER BY column1, column2, ... ASC|DESC;
QUIT;
nome_tabela %>% select(coluna1, coluna2, ...) %>%
arrange(column1, column2, ...)
Por padrão tanto o R qual SAS classificam os registros em ordem crescente. Para classificar os registros em ordem decrescente, no SAS adiciona-se DESC
após o nome da coluna deseja, e no R aplica-se a função desc()
na coluna desejada.
Vamos selecionar as colunas Model, Type e Cylinders, ordenar primeiramente de forma crescente por Type e descrescente por Cylinders:
PROC SQL;
SELECT Model, Type, Cylinders
FROM CARS
ORDER BY Type, Cylinders DESC;
QUIT;
CARS %>% select(Model, Type, Cylinders) %>%
arrange(Type, desc(Cylinders))
Resultado:
Podemos criar novas variáveis como funções das existentes ou talvez apenas renomeando, a seguir abordaremos esses casos.
Para obter a soma de uma coluna basta:
PROC SQL;
SELECT coluna1, coluna2, ...
SUM(coluna1) as sum_coluna1
FROM nome_tabela;
QUIT;
nome_tabela %>%
select(coluna1, coluna2, ...) %>%
mutate(sum_coluna1 = sum(column1))
Para obter a média, mínimo, máximo e a contagem de uma coluna devemos substituir sum()
por mean()
, min()
, max()
e count()
, respectivamente.
PROC SQL;
SELECT Model, Cylinders, Horsepower,
MEAN(Horsepower) as media_HP
FROM CARS;
QUIT;
CARS %>% select(Model, Cylinders, Horsepower) %>%
mutate(media_HP = mean(Horsepower))
Resultado:
A instrução CASE passa por condições e retorna um valor quando a primeira condição é atendida (como uma instrução IF-THEN-ELSE). Então, uma vez que uma condição é verdadeira, ela irá parar de ler e retornar o resultado. Se nenhuma condição for verdadeira, retornará o valor na cláusula ELSE.
Sintaxe:
PROC SQL;
SELECT coluna1, coluna2, ...
CASE
WHEN condição1 THEN resultado1
WHEN condição2 THEN resultado2
WHEN condiçãoN THEN resultadoN
ELSE resultado
END AS caso_coluna
FROM nome_tabela;
QUIT;
nome_tabela %>%
select(coluna1, coluna2, ...) %>%
mutate(caso_coluna = case_when(condição1 ~ resultado1,
condição2 ~ resultado2,
condiçãoN ~ resultadoN,
TRUE ~ resultado))
Selecionar colunas Model, Cylinders, Horsepower, Origin e criar uma coluna chamada origem que recebe ‘Europeu’ se Origin igual a ‘Europe’, caso contrário recebe ‘Outros’:
PROC SQL;
SELECT Model, Cylinders, Horsepower, Origin,
CASE
WHEN Origin = 'Europe' THEN 'Europeu'
ELSE 'Outros'
END AS origem
FROM CARS;
QUIT;
CARS %>% select(Model, Cylinders, Horsepower, Origin ) %>%
mutate(
origem = case_when(
Origin == 'Europe' ~ 'Europeu',
Origin != 'Europe' ~ 'Outros')
)
Resultado:
Grande parte das operações realizadas com dados requer a definição de grupos por variáveis.
O agrupamento, geralmente, é usado com funções agregadas (count(), max(), min(), sum(), mean()) para agrupar o conjunto de resultados em uma ou mais colunas.
PROC SQL;
SELECT coluna1, coluna2, ...
FROM nome_tabela
GROUP BY coluna1, coluna2,...;
QUIT;
nome_tabela %>%
group_by(coluna1, coluna2,...)
Caso não haja mais interesse em permanecer com o conjunto de dados agrupado, em R, deve-se aplicar a função ungroup()
, caso contrário todas as operações realizadas na sequencia neste conjunto de dados será realizada considerando os grupos definidos. Em SAS não há essa preocupação, mas caso queira permanecer a fazer operações com o mesmo grupo, deve-se replicar o agrupamento a cada seleção.
Selecionar as colunas Model, Type, Horsepower, e criar coluna da média de Horsepower por Type:
PROC SQL;
SELECT Model, Type, Horsepower,
mean(Horsepower) as media_HP
FROM CARS
GROUP BY Type;
QUIT;
CARS %>% select(Model, Type, Horsepower) %>%
group_by(Type) %>%
mutate(media_HP = mean(Horsepower))
Resultado:
Caso desejemos obter apenas as colunas media_HP e Type o dplyr proporciona um atalho utilizando summarise()
, enquanto que em SAS devemos selecionar apenas as variáveis desejadas e aplicar o argumento DISTINCT
, veja:
PROC SQL;
SELECT DISTINCT Type,
mean(Horsepower) as media_HP
FROM CARS
GROUP BY Type;
QUIT;
CARS %>% group_by(Type) %>% summarise(media_HP = mean(Horsepower))
Resultado:
Até o presente momento apenas fizemos consultas e transformações a partir de uma tabela de dados existente, mas não armazenamos estas consultas e transformações. No R para armazenarmos a consulta basta indicar um objeto para recebe-la, já no SAS podemos utilizar a instrução CREATE TABLE
(esta instrução também permite criar tabela especificando manualmente as entradas, porém aqui nos restringiremos a criação de tabelas a partir de consultas a tabelas existentes).
Sintaxe para criação de tabela:
PROC SQL;
CREATE TABLE nome_nova_tabela AS
SELECT coluna1, coluna2, ...
FROM nome_tabela;
QUIT;
nome_nova_tabela <- nome_tabela %>% select(coluna1, coluna2, ...)
Exemplo:
PROC SQL;
CREATE TABLE fabricante_origem AS
SELECT DISTINCT Make, Origin
FROM CARS;
QUIT;
fabricante_origem <- CARS %>% select(Make, Origin) %>% distinct()
Desta forma, ao consultar a tabela fabricante_origem
, obteremos o seguinte resultado sem necessidade de fazer o tratamento na tabela original (CARS) novamente:
Uma cláusula JOIN é usada para combinar linhas de duas ou mais tabelas, com base em uma coluna relacionada entre elas.
Esquema gráfico para representar os diversas formas de união entre tabelas com SQL.
Para exemplificar a união de tabelas vamos construir duas tabelas amostradas a partir do dataset CARS, utilizaremos a variável Model como chave primária para as uniões.
Tabela CARS_1:
Tabela CARS_2:
Retorna registros que possuem valores correspondentes nas duas tabelas.
Sintaxe para INNER JOIN de tabelas:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM tabela_1 INNER JOIN tabela_2
ON tabela_1.nome_coluna = tabela_2.nome_coluna;
QUIT;
tabela_1 %>% inner_join(tabela_2, by = 'nome_coluna' ) %>% select(coluna1, coluna2, ...)
PROC SQL;
SELECT *
FROM CARS_1 INNER JOIN CARS_2
ON CARS_1.Model = CARS_2.Model;
QUIT;
CARS_1 %>% inner_join(CARS_2, by = 'Model' )
Resultado:
Retorna todos os registros da tabela à esquerda e os registros correspondentes da tabela à direita.
Sintaxe para LEFT JOIN de tabelas:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM tabela_1 LEFT JOIN tabela_2
ON tabela_1.nome_coluna = tabela_2.nome_coluna;
QUIT;
tabela_1 %>% left_join(tabela_2, by = 'nome_coluna' ) %>% select(coluna1, coluna2, ...)
PROC SQL;
SELECT *
FROM CARS_1 LEFT JOIN CARS_2
ON CARS_1.Model = CARS_2.Model;
QUIT;
CARS_1 %>% left_join(CARS_2, by = 'Model' )
Resultado:
Retorna todos os registros da tabela à direita e os registros correspondentes da tabela à esquerda.
Sintaxe para RIGHT JOIN de tabelas:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM tabela_1 RIGHT JOIN tabela_2
ON tabela_1.nome_coluna = tabela_2.nome_coluna;
QUIT;
tabela_1 %>% right_join(tabela_2, by = 'nome_coluna' ) %>% select(coluna1, coluna2, ...)
PROC SQL;
SELECT *
FROM CARS_1 RIGHT JOIN CARS_2
ON CARS_1.Model = CARS_2.Model;
QUIT;
CARS_1 %>% right_join(CARS_2, by = 'Model' )
Resultado:
Retorna todos os registros quando há uma correspondência na tabela esquerda ou direita.
Sintaxe para FULL JOIN de tabelas:
PROC SQL;
SELECT coluna1, coluna2, ...
FROM tabela_1 FULL JOIN tabela_2
ON tabela_1.nome_coluna = tabela_2.nome_coluna;
QUIT;
tabela_1 %>% full_join(tabela_2, by = 'nome_coluna' ) %>% select(coluna1, coluna2, ...)
PROC SQL;
SELECT *
FROM CARS_1 FULL JOIN CARS_2
ON CARS_1.Model = CARS_2.Model;
QUIT;
CARS_1 %>% full_join(CARS_2, by = 'Model' )
Resultado:
Curso SAS Programming for R Users, https://support.sas.com/edu/schedules.html?ctry=br&crs=SP4R