Considerações iniciais

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-1.R

Essa publicação possui uma continuação em Manipulando com dplyr - Parte 2: bind() e join(): https://rpubs.com/reisrgabriel/dplyrPt2

Foi utilizado o banco de dados DASS42, retirado desse desafio do Kaggle: https://www.kaggle.com/lucasgreenwell/depression-anxiety-stress-scales-responses?select=data.csv

Os participantes que responderam foram os que procuraram a plataforma OpenPsychometrics.org e responderam a pesquisa do site.

Sobre o dplyr

O pacote dplyr possui várias funções interessantes que permitem:

  • Selecionar variáveis de maneira dinâmica e fácil.
  • Criar novas variáveis a partir de variáveis antigas.
  • Sumarizar vários valores em um só.
  • Filtrar e agrupar variáveis de interesse a partir de condições específicas.

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:


Usando select()

Diagnósticos iniciais

A primeira tarefa quando se trata de manipular um banco de dados consiste na importação correta dos dados ao software de programação.

Vamos ler o nosso banco com a função base do R read.csv().

dass <- read.csv("https://raw.githubusercontent.com/GabrielReisR/R/master/estrutura%20de%20dados/dados/dass42.csv")

Agora, vamos ver como está a estrutura desse banco.

dass[1:10,] # vamos ver os primeiros 10 casos

Vamos começar a manipular com o dplyr.

Selecionando e excluindo variáveis

Para usar o dplyr, basta ler o pacote com o comando a seguir:

library(dplyr) # caso não o possua, instale com 'install.packages("dplyr")'

Para manipular o banco, vamos sempre usar a seguinte fórmula:

banco <- banco %>% # atribuímos a banco o mesmo valor de banco
  funcao() # modificamos o banco com dplyr

O indicador %>% se chama pipe, ou cano em português. Ele nos permite acessar o banco diretamente, e a partir disso realizar as mudanças que desejamos.

Dica: o comando rápido para o pipe é Ctrl + Shift + M.

O primeiro verbo (em inglês, verb) que a gente vai tratar vai ser o select(). Ele permite:

  • Selecionar apenas as variáveis desejadas.
  • Excluir variáveis.
  • Renomear variáveis.
  • Trocar a posição de variáveis.

Vamos fazer algo simples: colocar a variável age(idade) para o início.

dass <- dass %>%
  select(age, everything())

dass[1:10, ] # Veja como 'age' agora é a primeira coluna!
  1. Usamos select() para selecionar a variável, nomeando-a sem aspas pois já estamos acessando o banco (por causa do pipe %>%).
  2. Colocamos age no início.
  3. Utilizamos a função everything() que coloca o restante das variáveis após a primeira.

Vamos agora colunas. Vamos excluir as colunas que vão de country até orientation. Para fazer isso, basta:

  • Colocar o sinal de menos - na frente das colunas que queremos excluir.
  • Como queremos um intervalo de colunas, de country até orientation, baste utilizar country:orientation.
  • Vamos concatenar essas várias colunas em um único objeto usando c().
dass <- dass %>%
  select(everything(), -c(country:orientation)) # excluir as colunas de 'country' à 'orientation'

names(dass) # Não existe mais as colunas de 'country' à 'orientation'
##   [1] "age"        "X"          "Q1A"        "Q1I"        "Q1E"       
##   [6] "Q2A"        "Q2I"        "Q2E"        "Q3A"        "Q3I"       
##  [11] "Q3E"        "Q4A"        "Q4I"        "Q4E"        "Q5A"       
##  [16] "Q5I"        "Q5E"        "Q6A"        "Q6I"        "Q6E"       
##  [21] "Q7A"        "Q7I"        "Q7E"        "Q8A"        "Q8I"       
##  [26] "Q8E"        "Q9A"        "Q9I"        "Q9E"        "Q10A"      
##  [31] "Q10I"       "Q10E"       "Q11A"       "Q11I"       "Q11E"      
##  [36] "Q12A"       "Q12I"       "Q12E"       "Q13A"       "Q13I"      
##  [41] "Q13E"       "Q14A"       "Q14I"       "Q14E"       "Q15A"      
##  [46] "Q15I"       "Q15E"       "Q16A"       "Q16I"       "Q16E"      
##  [51] "Q17A"       "Q17I"       "Q17E"       "Q18A"       "Q18I"      
##  [56] "Q18E"       "Q19A"       "Q19I"       "Q19E"       "Q20A"      
##  [61] "Q20I"       "Q20E"       "Q21A"       "Q21I"       "Q21E"      
##  [66] "Q22A"       "Q22I"       "Q22E"       "Q23A"       "Q23I"      
##  [71] "Q23E"       "Q24A"       "Q24I"       "Q24E"       "Q25A"      
##  [76] "Q25I"       "Q25E"       "Q26A"       "Q26I"       "Q26E"      
##  [81] "Q27A"       "Q27I"       "Q27E"       "Q28A"       "Q28I"      
##  [86] "Q28E"       "Q29A"       "Q29I"       "Q29E"       "Q30A"      
##  [91] "Q30I"       "Q30E"       "Q31A"       "Q31I"       "Q31E"      
##  [96] "Q32A"       "Q32I"       "Q32E"       "Q33A"       "Q33I"      
## [101] "Q33E"       "Q34A"       "Q34I"       "Q34E"       "Q35A"      
## [106] "Q35I"       "Q35E"       "Q36A"       "Q36I"       "Q36E"      
## [111] "Q37A"       "Q37I"       "Q37E"       "Q38A"       "Q38I"      
## [116] "Q38E"       "Q39A"       "Q39I"       "Q39E"       "Q40A"      
## [121] "Q40I"       "Q40E"       "Q41A"       "Q41I"       "Q41E"      
## [126] "Q42A"       "Q42I"       "Q42E"       "race"       "voted"     
## [131] "married"    "familysize" "major"

Nesse exemplo, selecionamos primeiro todas as variáveis usando everything() e depois excluímos todas as colunas desde country até orientation. Para selecionar ou excluir colunas diferentes, basta dividir os argumentos por vírgula. Ou seja, se eu quisesse também excluir age, bastaria usar -c(country:orientation, age).

Agora vamos renomear a coluna age para ter o nome idade. Para fazer isso, basta seguir a fórmula: novo nome = nome antigo. Ou seja, atribua a essa nova variável o mesmo valor da variável antiga.

dass <- dass %>%
  select(idade = age, everything())

dass[1:10, ]

Podemos fazer isso também com rename. Vamos agora utilizar o processo inverso, de idade para age:

dass <- dass %>%
  rename(age = idade) # note que somente escrevemos as colunas que desejamos modificar

dass[1:10, ]

Seleção com condição

Agora vamos utilizar três funções bem interessantes que podem ser utilizadas com select():

  • starts_with(): escolhe colunas que comecem com uma string.
  • ends_with(): escolhe colunas que terminem com uma string.
  • contains(): escolhe colunas que contenham uma string.

Se quiséssemos, por exemplo, encontrar todas as colunas que comecem com a letra “T”, poderíamos utilizar starts_with("T").

Para acessar todas as variáveis que terminam com “n”, poderíamos utilizar ends_with("n").

Para acessar todas as colunas que contenham em seu nome a letra “Q”, basta usar contains("Q").

dass <- dass %>%
  select(everything(), # embora esteja sendo usado, não é necessário para essa função
         -starts_with("T"), # excluindo apenas as variáveis que começam com 'T'
         -starts_with("V"), # excluindo apenas as variáveis que começam com 'V'
         -ends_with("I"), # excluindo apenas as variáveis que terminam com 'I'
         contains("Q")) # selecionando apenas as variáveis que contenham 'Q'

names(dass) # Vamos ver quais nomes sobraram!
##   [1] "age"        "X"          "Q1A"        "Q1E"        "Q2A"       
##   [6] "Q2E"        "Q3A"        "Q3E"        "Q4A"        "Q4E"       
##  [11] "Q5A"        "Q5E"        "Q6A"        "Q6E"        "Q7A"       
##  [16] "Q7E"        "Q8A"        "Q8E"        "Q9A"        "Q9E"       
##  [21] "Q10A"       "Q10E"       "Q11A"       "Q11E"       "Q12A"      
##  [26] "Q12E"       "Q13A"       "Q13E"       "Q14A"       "Q14E"      
##  [31] "Q15A"       "Q15E"       "Q16A"       "Q16E"       "Q17A"      
##  [36] "Q17E"       "Q18A"       "Q18E"       "Q19A"       "Q19E"      
##  [41] "Q20A"       "Q20E"       "Q21A"       "Q21E"       "Q22A"      
##  [46] "Q22E"       "Q23A"       "Q23E"       "Q24A"       "Q24E"      
##  [51] "Q25A"       "Q25E"       "Q26A"       "Q26E"       "Q27A"      
##  [56] "Q27E"       "Q28A"       "Q28E"       "Q29A"       "Q29E"      
##  [61] "Q30A"       "Q30E"       "Q31A"       "Q31E"       "Q32A"      
##  [66] "Q32E"       "Q33A"       "Q33E"       "Q34A"       "Q34E"      
##  [71] "Q35A"       "Q35E"       "Q36A"       "Q36E"       "Q37A"      
##  [76] "Q37E"       "Q38A"       "Q38E"       "Q39A"       "Q39E"      
##  [81] "Q40A"       "Q40E"       "Q41A"       "Q41E"       "Q42A"      
##  [86] "Q42E"       "race"       "married"    "familysize" "major"     
##  [91] "Q1I"        "Q2I"        "Q3I"        "Q4I"        "Q5I"       
##  [96] "Q6I"        "Q7I"        "Q8I"        "Q9I"        "Q10I"      
## [101] "Q11I"       "Q12I"       "Q13I"       "Q14I"       "Q15I"      
## [106] "Q16I"       "Q17I"       "Q18I"       "Q19I"       "Q20I"      
## [111] "Q21I"       "Q22I"       "Q23I"       "Q24I"       "Q25I"      
## [116] "Q26I"       "Q27I"       "Q28I"       "Q29I"       "Q30I"      
## [121] "Q31I"       "Q32I"       "Q33I"       "Q34I"       "Q35I"      
## [126] "Q36I"       "Q37I"       "Q38I"       "Q39I"       "Q40I"      
## [131] "Q41I"       "Q42I"

Renomeando múltiplas colunas

Agora que sabemos selecionar variáveis, vamos selecionar apenas as variáveis que nos interessam para a correção da DASS. As respostas à DASS42 estão presentes em todas as colunas que possuem “Q” no início e que terminam com “A”.

dass <- dass %>%
  select(starts_with("Q") & ends_with("A")) # note a utilização do valor '&'

Vamos renomear dinamicamente todas essas variáveis, dando o nome de dass_n (dass + número do item) ao invés de QnA, como está agora. Vamos ver como estão os nomes das colunas do nosso banco usando names().

dass <- dass %>%
  select(dass_ = starts_with("Q")) # dass_ será o nome de todas as variáveis que comecem com "Q"

names(dass) # permite ver os nomes das colunas de dass
##  [1] "dass_1"  "dass_2"  "dass_3"  "dass_4"  "dass_5"  "dass_6"  "dass_7" 
##  [8] "dass_8"  "dass_9"  "dass_10" "dass_11" "dass_12" "dass_13" "dass_14"
## [15] "dass_15" "dass_16" "dass_17" "dass_18" "dass_19" "dass_20" "dass_21"
## [22] "dass_22" "dass_23" "dass_24" "dass_25" "dass_26" "dass_27" "dass_28"
## [29] "dass_29" "dass_30" "dass_31" "dass_32" "dass_33" "dass_34" "dass_35"
## [36] "dass_36" "dass_37" "dass_38" "dass_39" "dass_40" "dass_41" "dass_42"

Entendendo melhor:

  • dass_ será o nome de todas as variáveis que comecem com “Q”.
  • dass_1 armazena o nome dessa primeira variável, Q1A.
  • dass_ reconhece outro valor, Q2A, e armazena no próximo número depois de dass_1, criando dass_2.
  • Esse processo se repete até dass_42.

Usando mutate()

Agora que temos todas as principais colunas, podemos começar a utilizar o mutate(), que nos permite

  • Criar novas variáveis a partir de variáveis do banco.
  • Adicionar variáveis novas.
  • Modificar valores de variáveis existentes.

Calculando escores da DASS

Antes de começar o cálculo, vamos lembrar que a DASS é respondida de 0 a 3, e aqui temos resposta de 1 a 4. Isso é importante pois os pontos de corte para a classificação de severidade partem de escores brutos das respostas.

Assim, precisamos que:

  • Todas as variáveis respondidas com 1 sejam 0
  • Todas as variáveis respondidas com 2 sejam 1
  • Todas as variáveis respondidas com 3 sejam 2
  • Todas as variáveis respondidas com 4 sejam 3

Ou seja, precisamos que x seja x - 1.

Para fazer isso, basta pedir o seguinte:

dass <- dass - 1 # isso já resolve!

Essa foi uma solução proposta pelo André Stephanou. Simples e super fácil né?

Com tudo isso pronto, vamos dar uma olhada no nosso banco.

dass[1:10, ] # vamos ver os primeiros 10 casos novamente

Parece tudo certo :)

Calculando depressão, ansiedade e estresse

Lembra que mutate() consegue alterar o valor de apenas uma variável por vez? Vamos utilizar ele agora para pegar o valor de outras variáveis e criar três novas.

Cada participante, cada linha (ou row em inglês), terá os valores do nível de depressão, ansiedade e estresse calculados como abaixo.

  • depressao: soma dos valores das colunas dass_2, dass_5, dass_12, dass_13, dass_16, dass_17, dass_20, dass_23, dass_25, dass_26, dass_31, dass_32, dass_36, dass_41
  • ansiedade: soma dos valores das colunas dass_1, dass_6, dass_8, dass_10, dass_11, dass_14, dass_21, dass_22, dass_27, dass_28, dass_34, dass_37, dass_40, dass_42
  • estresse: soma dos valores das colunas dass_3, dass_4, dass_7, dass_9, dass_15, dass_18, dass_19, dass_24, dass_29, dass_30, dass_33, dass_35, dass_38, dass_39

Para acessar o valor de cada linha para fazer esse cálculo - ou seja, para que a soma das colunas diga respeito a cada um dos participantes - vamos utilizar o verbo rowwise() antes de realizar o cálculo. Fica assim:

dass <- dass %>%
  rowwise() %>% # para o cálculo ser realizado em cada linha
  mutate(
    # criando a variável 'depressao'
    depressao = sum(dass_2, dass_5, dass_12, dass_13, dass_16, dass_17, dass_20, dass_23, dass_25, dass_26, dass_31, dass_32, dass_36, dass_41),
    
    # criando a variável 'ansiedade'
    ansiedade = sum(dass_1, dass_6, dass_8, dass_10, dass_11, dass_14, dass_21, dass_22, dass_27, dass_28, dass_34, dass_37, dass_40, dass_42),
    
    # criando a variável 'estresse'
    estresse = sum(dass_3, dass_4, dass_7, dass_9, dass_15, dass_18, dass_19, dass_24, dass_29, dass_30, dass_33, dass_35, dass_38, dass_39)
  )

Perceba que basta utilizar a função sum() para somar os valores.

Para acessar isso, basta olhar para como está o banco agora (você pode fazer isso com dass %>% glimpse()).

Classificando o nível de severidade

Agora que temos os escores de cada pessoa na escala DASS42, vamos classificar esses escores por nível de gravidade/severidade.

Para isso, existe uma função bem útil que se chama case_when. Especificamos uma condição baseada em outra variável, e assim que essa condição é atendida, determinado valor é criado. Vamos utilizá-la dentro de mutate() para criar nossas classificações.

dass <- dass %>%
  mutate(
    # classificação do nível de depressão
    nivel_dep = case_when(depressao < 10 ~ "Normal",
                          depressao >= 10 & depressao < 14 ~ "Leve",
                          depressao >= 14 & depressao < 21 ~ "Moderado",
                          depressao >= 21 & depressao < 28 ~ "Severo",
                          depressao >= 28 ~ "Extremamente Severo"),
    # classificação do nível de ansiedade
    nivel_ans = case_when(ansiedade < 8 ~ "Normal",
                          ansiedade >= 8 & ansiedade < 10 ~ "Leve",
                          ansiedade >= 10 & ansiedade < 15 ~ "Moderado",
                          ansiedade >= 15 & ansiedade < 20 ~ "Severo",
                          ansiedade >= 20 ~ "Extremamente Severo"),
    # classificação do nível de estresse
    nivel_est = case_when(estresse < 15 ~ "Normal",
                          estresse >= 15 & estresse < 19 ~ "Leve",
                          estresse >= 19 & estresse < 25 ~ "Moderado",
                          estresse >= 25 & estresse < 34 ~ "Severo",
                          estresse >= 34 ~ "Extremamente Severo")
  )
  • A função acima criou três novos objetos (nivel_dep/ans/est) baseando-se nos valores de suas respectivas colunas.
  • case_when() considera a primeira condição e atribui o valor que queremos a essa condição.
  • No primeiro caso, quando a variável depressao for menor que 10 atribui-se a essa nova coluna o valor “Normal”: depressao < 10 ~ "Normal"
  • Para fornecer as outras condições, basta colocar uma vírgula e continuar.
  • Para valores que fogem ao que a função consegue oferecer, poderia-se criar a condição TRUE ~ ., atribuindo um valor específico caso nenhuma outra condição satisfaça o que está send pedido.

Assim que criado, podemos transformar essas novas variáveis em fatores. Isso pode ser feito diretamente com R. Vamos criar um hiperparâmetro chamado nivelSeveridade.

nivelSeveridade <- c("Normal", "Leve", "Moderado", "Severo", "Extremamente Severo")

dass$nivel_dep <- dass$nivel_dep %>% as.factor # transformar em fator
dass$nivel_dep <- factor(dass$nivel_dep,
                         levels = nivelSeveridade, # colocar em ordem
                         labels = nivelSeveridade) # colocar em ordem

dass$nivel_ans <- dass$nivel_ans %>% as.factor  # transformar em fator
dass$nivel_ans <- factor(dass$nivel_ans, 
                         levels = nivelSeveridade, # colocar em ordem
                         labels = nivelSeveridade) # colocar em ordem

dass$nivel_est <- dass$nivel_est %>% as.factor # transformar em fator
dass$nivel_est <- factor(dass$nivel_est,
                         levels = nivelSeveridade, # colocar em ordem
                         labels = nivelSeveridade) # colocar em ordem

Pronto! Fizemos todas as alterações iniciais. Temos o resultado de todos participantes e suas classificações.

Vamos ver quantos participantes (nrow()) possuem nível de depressão, ansiedade e estresse considerados como “Severo” ou “Extremamente Severo”. Vamos adicionar essas pessoas ao novo banco de dados chamado casosGraves.

Vamos utilizar filter(), uma função do dplyr.

casosGraves <- dass %>% # criando um novo banco de dados chamado CasosGraves
  filter(nivel_dep == "Severo" | nivel_dep == "Extremamente Severo",
         nivel_ans == "Severo" | nivel_ans == "Extremamente Severo",
         nivel_est == "Severo" | nivel_est == "Extremamente Severo")

nrow(casosGraves)
## [1] 10431
casosGraves[1:10, ] # vamos ver os 10 primeiros casos

Dos 39775 participantes, 10431 apresentam sintomas de Depressão + Ansiedade + Estresse no nível Severo ou acima!

Ou seja, 26,22% da amostra preencheram nosso critério arbitrário de gravidade. Aqui, tenho a hipótese de que esse número seja alto por conta de um viés amostral no momento de coleta de dados. Explico melhor.

Os dados foram coletados das pessoas que entraram na plataforma OpenPsychometrics.org e resolveram responder à pesquisa sobre depressão, ansiedade e estresse. É possível que o público que busca e que é interessado em responder a testes de ansiedade e depressão na internet sejam pessoas mais ansiosas.

Espero que você tenha entendido o quão poderoso pode ser o dplyr.

Por enquanto é isso! :)


Mais informações

Manipulando com dplyr - Parte 2: bind() e join(): https://rpubs.com/reisrgabriel/dplyrPt2

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