Esse é um documento feito para ensinar e para reforçar conteúdos de manipulação de dados usando dplyr. Qualquer comentário, erro ou sugestão, é só falar comigo entrando em contato através de qualquer uma das opções listadas em Contato.
O script em R está disponível aqui: https://github.com/GabrielReisR/R/blob/master/estrutura%20de%20dados/dplyr-parte-2.R
Essa publicação é uma continuação de Manipulando com dplyr - Parte 1: select() e mutate(): https://rpubs.com/reisrgabriel/dplyrPt1
O pacote dplyr possui várias funções interessantes que permitem:
Em suma, o dplyr é um pacote muito versátil e bastante útil para manipulação de dados em objetos data.frame.
Para maiores informações sobre o dplyr:
Em muitas situações unir dois bancos de dados é uma necessidade. Assim como na Parte 1, vamos utilizar funções do dplyr que facilitam realizar essa manipulação.
Vamos começar com a situação mais simples: dois bancos de dados nos quais os casos estão ordenados e basta apenas juntá-los. Ou seja, o participante da linha 1 no banco 1 é o mesmo participante da linha 1 no banco 2, e assim por diante.
Esse é o caso mais simples de união de dois bancos. Para demonstrá-lo, não é necessário importar um banco de dados. Basta criar dois data.frames com algumas linhas de código.
Vou criar 2 bancos, cada um com duas colunas e cinco casos.
col1 <- c(letters[1:5]) # letras de 1 a 5
col2 <- sample(c(1:5), size = 5, replace = FALSE) # numeros de 1 a 5
col3 <- sample(c(100:2500), size = 5, replace = TRUE) # numeros aleatorios de 100 a 2500
col4 <- sample(c(100:2500), size = 5, replace = TRUE) # numeros aleatorios de 100 a 2500
dataframe1 <- data.frame(col1, col2) # criando df1
dataframe2 <- data.frame(col3, col4) # criando df2
dataframe1
dataframe2
Para juntar ambos os bancos pela sua posição, basta utilizar a função bind_cols() presente no pacote dplyr. Ela possui a forma bind_cols(df1, df2).
library(dplyr) # lendo dplyr
dataframe_completo <- bind_cols(dataframe1, dataframe2) # usando bind_cols()
dataframe_completo
É bem simples! Como podemos ver, os bancos foram unidos pela posição das variáveis.
Com bind_rows() a lógica é a mesma. A coluna 1 no banco 1 representa a mesma variável da coluna 1 no banco 2. Quando um data.frame e outro possuem variáveis iguais, os casos são adicionados. Quando as colunas diferem de nome, os casos que não possuem valor nessa coluna recebem o valor de missing NA.
lista <- list(col1 = "a", col2 = 4, col3 = 1028, col4 = 255, col5 = 9902)
dataframe_completo <- bind_rows(dataframe_completo, lista)
dataframe_completo
Pronto! Já que nenhuma linha possui valores na coluna 5, isso é preenchido como NA, assim como explicado acima.
Vamos para funções mais completas e que levam em conta bancos de dados com mais informações. Os mutating joins são funções que unem bancos baseados em condições específicas. Vou explicar.
Considere os bancos a seguir:
dass_dep <- read.csv("https://raw.githubusercontent.com/GabrielReisR/R/master/estrutura%20de%20dados/dados/dass_dep.csv")
dass_ans <- read.csv("https://raw.githubusercontent.com/GabrielReisR/R/master/estrutura%20de%20dados/dados/dass_ans.csv")
dass_est <- read.csv("https://raw.githubusercontent.com/GabrielReisR/R/master/estrutura%20de%20dados/dados/dass_est.csv")
São os mesmos casos que vimos no bloco 2. Abaixo as características dos bancos.
Como juntar bancos com colunas de nomes iguais? Quais casos aceitar ou não?
Temos algumas opções:
full_join(): todos os casos entram.inner_join(): todos os casos em comum em todos os bancos entram.left_join(): todos os casos do primeiro banco ficam, os casos em comum com o segundo banco também entram.right_join(): todos os casos do segundo banco ficam, os casos em comum com o primeiro banco também entram.Vamos começar com a opção menos excludente.
Um full_join nos permite incluir todos os casos do banco x e do banco y ao mesmo tempo. Assim, todos os casos que existem no banco 2 serão também adicionados ao banco 1.
Para fazer qualquer join, possuímos duas funções bem importantes:
by(): escolhe qual argumento ambos bancos tem em comum.suffix(): auxilia colocando um sufixo em colunas de nome idêntico.Sabendo que nos dois bancos temos todas as respostas da DASS, precisamos fazer duas transformações. Antes de começar, vamos excluir as respostas da DASS do banco dass_ans e dass_est. Aproveitaremos e já excluíremos a coluna “X” de todos os bancos.
dass_dep <- dass_dep %>%
select(-X) # excluindo a coluna X
dass_ans <- dass_ans %>%
select(id_ans, escore_total, nivel) # selecionando id_ans, escore_total e nivel
dass_est <- dass_est %>%
select(id_est, escore_total, nivel) # selecionando id_est, escore_total e nivel
names(dass_dep) # nomes das colunas do banco 'dass_dep'
## [1] "id" "dass_1" "dass_2" "dass_3" "dass_4"
## [6] "dass_5" "dass_6" "dass_7" "dass_8" "dass_9"
## [11] "dass_10" "dass_11" "dass_12" "dass_13" "dass_14"
## [16] "dass_15" "dass_16" "dass_17" "dass_18" "dass_19"
## [21] "dass_20" "dass_21" "dass_22" "dass_23" "dass_24"
## [26] "dass_25" "dass_26" "dass_27" "dass_28" "dass_29"
## [31] "dass_30" "dass_31" "dass_32" "dass_33" "dass_34"
## [36] "dass_35" "dass_36" "dass_37" "dass_38" "dass_39"
## [41] "dass_40" "dass_41" "dass_42" "escore_total" "nivel"
names(dass_ans) # nomes das colunas do banco 'dass_ans'
## [1] "id_ans" "escore_total" "nivel"
names(dass_est) # nomes das colunas do banco 'dass_est'
## [1] "id_est" "escore_total" "nivel"
Agora, entendendo os novos nomes, podemos começar.
dass_total <- dass_dep %>% # sempre se começa a partir de um banco
full_join(dass_ans, by = c("id" = "id_ans"), suffix = c("_dep", "_ans"))
dass_total
O que aconteceu aqui foi o seguinte:
full_join(), chamamos o banco a ser juntado, dass_ans.by() que a coluna “id” do primeiro banco é igual à coluna “id_ans” do segundo banco (by = c("id" = "id_ans")), delimitando que (1) essas colunas deveriam ser iguais e que os valores dos casos deveriam ser posicionados de acordo com essa coluna.
by = "id".suffix(), para todas as colunas com nome igual, adicionamos um sufixo no primeiro banco chamado "_dep" e um sufixo no segundo banco chamado "_ans" (suffix = c("_dep", "_ans")).O processo agora pode ser o mesmo (e ele é segue essa linha para todos os mutating-joins).
dass_total <- dass_total %>%
full_join(dass_est, by = c("id" = "id_est")) %>%
rename(escore_total_est = escore_total, # renomear a coluna escore_total
nivel_est = nivel) # renomear a coluna nivel
dass_total # full join concluído!
1000 casos! Isso aconteceu porque todos os casos foram adicionados.
Um inner join escolhe apenas os casos que existam no banco x E no banco y. Os casos em comum são juntados. A fórmula é a mesma, então vamos direto à ela.
dass_inner <- dass_dep %>%
inner_join(dass_ans, by = c("id" = "id_ans"), suffix = c("_dep", "_ans")) %>%
inner_join(dass_est, by = c("id" = "id_est")) %>%
rename(escore_total_est = escore_total, # renomear a coluna escore_total
nivel_est = nivel) # renomear a coluna nivel
dass_inner
Pronto! Podemos ver que o número de casos diminuiu. Isso porque só os que estavam no banco dass_dep, dass_ans e dass_est ao mesmo tempo que entraram no banco.
O left join, como o nome diz, preserva o primeiro banco (o banco da esquerda). Todos os casos da esquerda são preservados, enquanto os outros são adicionados.
dass_left <- dass_dep %>%
left_join(dass_ans, by = c("id" = "id_ans"), suffix = c("_dep", "_ans")) %>%
left_join(dass_est, by = c("id" = "id_est")) %>%
rename(escore_total_est = escore_total, # renomear a coluna escore_total
nivel_est = nivel) # renomear a coluna nivel
dass_left
Temos novamente 1000 casos! Isso porque preservamos o banco dass_dep primeiro, e ele possui 1000 casos.
O right join, como o nome diz, preserva o segundo banco (o banco da direita). Todos os casos da direita são preservados, enquanto os outros são adicionados.
dass_right <- dass_dep %>%
right_join(dass_ans, by = c("id" = "id_ans"), suffix = c("_dep", "_ans")) %>%
right_join(dass_est, by = c("id" = "id_est")) %>%
rename(escore_total_est = escore_total, # renomear a coluna escore_total
nivel_est = nivel) # renomear a coluna nivel
dass_right
Temos 900 casos agora. Isso acontece porque preservamos primeiro o banco da direita (dass_ans), que possuía 900 casos.
Enquanto os mutating joins se importam em unir bancos baseados em condições, os filter joins são construídos para filtrar casos de um banco a outro, não necessariamente para unir bancos.
O semi join retorna todos os valores do banco x que também estão no banco y. Ao fazer isso, ele não incorpora as colunas e variáveis de y. Ou seja, assim como o próximo verbo que vamos tratar (anti_join()), o semi_join é uma função filtro, pois retorna as colunas de apenas um banco se baseando nos casos de outro banco.
Vamos fazer o semi-join entre dass_dep e os outros bancos. Notemos que, aqui, não é necessário renomear variáveis ou colocar sufixos, pois as colunas de dass_ans e dass_est não serão incorporadas.
dass_semi <- dass_dep %>%
semi_join(dass_ans, by = c("id" = "id_ans")) %>%
semi_join(dass_est, by = c("id" = "id_est"))
dass_semi
Aqui temos 809 casos. Por quê?
Sendo assim, apenas esses últimos permaneceram. Vale ressaltar que nenhuma nova coluna foi adicionada.
Esse é o último join que veremos aqui e ele é bem interessante. Ele preserva apenas os casos que estão em x e que não estão em y. Assim, só se salva quem está no banco da esquerda e que não está nos outros bancos.
dass_anti <- dass_dep %>%
anti_join(dass_ans, by = c("id" = "id_ans")) %>%
anti_join(dass_est, by = c("id" = "id_est"))
dass_anti
Apenas 9 casos estão no primeiro banco e não são compartilhados com os demais!
Por enquanto é isso :)
Manipulando com dplyr - Parte 1: select() e mutate(): https://rpubs.com/reisrgabriel/dplyrPt1
Organizando com tidyr - Parte 1: dados wide e long: https://rpubs.com/reisrgabriel/tidyrPt1
Organizando com tidyr - Parte 2: valores missing: https://rpubs.com/reisrgabriel/tidyrPt2
Importação de dados e diagnósticos iniciais: https://rpubs.com/reisrgabriel/importdiagn
Para maiores informações sobre o dplyr: https://dplyr.tidyverse.org/ ou https://github.com/rstudio/cheatsheets/blob/master/data-transformation.pdf