Bem-vindo
Este é um tutorial do Prof Henrique Alvarenga para alunos da disciplina Análise de dados com a Linguarem R, do curso de medicina da UFSJ.
O Objetivo desse tutorial é aprender a filtrar observações em um data
frame usando filter() e usar operadores lógicos para
extrair observações de um data frame. Esse tutorial foi traduzido a
partir do código-fonte
que o gerou.
Neste tutorial, você aprenderá a:
- Usar
filter()para extrair observações de um data frame ou tibble - Escrever testes lógicos em R
- Combinar testes lógicos com operadores Booleanos
- Lidar com valores ausentes dentro de testes lógicos
As leituras deste tutorial seguem a seção 5.2 do livro R for Data Science.
Pré-requisitos
Para praticar essas habilidades, usaremos o conjunto de dados
diabetes. Esses dados são cortesia do Dr. John Schorling,
Departamento de Medicina, Faculdade de Medicina da Universidade da
Virgínia. Os dados consistem em 19 variáveis em 403 indivíduos de 1046
indivíduos que foram entrevistados em um estudo para compreender a
prevalência de obesidade, diabetes e outros fatores de risco
cardiovascular na Virgínia central para afro-americanos. De acordo com
John Hong, Diabetes Mellitus Tipo II (DM II) está associado à obesidade
e a relação entre a estatura / quadril pode ser um preditor de diabetes
e doenças cardíacas. DM II também também está associado à
hipertensão.
Para fins desse estudo iremos considerar um nível de hemoglobina glicosilada acima de 7 como um sinal positivo de diabetes.
Para mais informações sobre este estudo, consulte Willems JP, Saunders JT, DE Hunt, JB Schorling: Prevalence of coronary heart disease risk factors among rural blacks: A community-based study. Southern Medical Journal 90:814-820; 1997 & Schorling JB, Roach J, Siegel M , Baturka N, Hunt DE, Guterbock TM , Stewart HL: A trial cessation interventions for rural African Americans. Preventive Medicine26:92-101; 1997.
Esses banco de dados pode ser obtido no endereço: https://hbiostat.org/data/
Também usaremos o pacote ggplot2 para visualizar os
dados.
Conhecendo os dados
Dicionário de Variáveis do Dataset de Diabetes
| Variável | Tipo | Descrição |
|---|---|---|
id |
Numérica | Identificador único do paciente. |
chol |
Numérica | Nível de colesterol total (mg/dL). |
stab.glu |
Numérica | Nível de glicose estável (mg/dL). |
hdl |
Numérica | Nível de colesterol HDL (mg/dL). |
ratio |
Numérica | Razão entre colesterol total e HDL. |
glyhb |
Numérica | Nível de hemoglobina glicada (%). |
location |
Categórica | Localização do paciente (Buckingham ou Louisa). |
age |
Numérica | Idade do paciente (anos). |
gender |
Categórica | Gênero do paciente (male ou female). |
height |
Numérica | Altura do paciente (polegadas). |
weight |
Numérica | Peso do paciente (libras). |
frame |
Categórica | Estrutura corporal (small, medium,
large). |
bp.1s |
Numérica | Pressão arterial sistólica na primeira leitura (mm Hg). |
bp.1d |
Numérica | Pressão arterial diastólica na primeira leitura (mm Hg). |
bp.2s |
Numérica | Pressão arterial sistólica na segunda leitura (mm Hg). |
bp.2d |
Numérica | Pressão arterial diastólica na segunda leitura (mm Hg). |
waist |
Numérica | Circunferência da cintura (polegadas). |
hip |
Numérica | Circunferência do quadril (polegadas). |
time.ppn |
Numérica | Tempo desde a última ingestão de comida até a coleta de sangue (minutos). |
Se estiver pronto para começar, clique em Começar!
Filtrar linhas com filter()
filter()
filter() permite que você use um teste lógico para
extrair linhas específicas de um data frame. Para usar
filter(), passe o data frame seguido de um ou mais testes
lógicos. filter() retornará todas as linhas que passarem em
cada teste lógico.
Por exemplo, podemos usar filter() para selecionar todos
os pacientes no conjunto diabetes do sexo feminino e da
cidade de Buckingham. Clique em Executar Código para tentar:
diabetes |>
filter(gender == "female", location == "Buckingham")
Saída
Como todas as funções do dplyr, filter() retorna um novo
data frame para você salvar ou usar. Ele não sobrescreve o data frame
original.
Se você quiser salvar a saída de filter(), precisará
usar o operador de atribuição <-.
Execute novamente o comando no bloco de código abaixo, mas primeiro
arranje para salvar a saída em um objeto chamado
BuckGirls.
filter(diabetes, gender == "female", location == "Buckingham")
BuckGirls <- filter(diabetes, gender == "female", location == "Buckingham")
Bom trabalho! Agora você pode ver os resultados executando o nome
BuckGirls por conta própria. Ou você pode passar
BuckGirls para uma função que aceita data frames como
entrada.
Você notou que esse código usou o operador de igualdade dupla,
==? == é um dos operadores de comparação
lógica do R. Operadores de comparação são fundamentais para usar
filter(), então vamos dar uma olhada neles.
Comparações Lógicas
Operadores de comparação
O R fornece um conjunto de operadores de comparação que você pode
usar para comparar valores: >, >=,
<, <=, != (diferente), e
== (igual). Cada um cria um teste lógico. Por exemplo, o
pi é maior que três?
pi > 3
## [1] TRUE
Quando você coloca um teste lógico dentro de filter(), o
filter aplica o teste a cada linha do data frame e, em
seguida, retorna as linhas que passam no teste, como um novo data
frame.
Nosso código acima retornou todas as linhas cujo valor do sexo
(gender) era igual a female e cujo valor da cidade
(location) era igual a Buckingham.
Atenção!
Quando você está começando com R, o erro mais comum é testar a
igualdade com = em vez de ==. Quando isso
acontecer, você receberá uma mensagem de erro informativa:
filter(diabetes, gender = "female")
## Error in `filter()`:
## ! We detected a named input.
## ℹ This usually means that you've used `=` instead of `==`.
## ℹ Did you mean `gender == "female"`?
Múltiplos testes
Se você passar mais de um teste lógico para filter(),
ele combinará os testes com um “e” implícito. Em outras palavras,
filter() retornará apenas as linhas que retornam
TRUE para todos os testes. Você pode combinar testes de
outras maneiras usando operadores booleanos.
Operadores Booleanos
&, |, e !
O R usa operadores booleanos para combinar múltiplas comparações
lógicas em um único teste lógico. Esses operadores incluem
& (e), | (ou),
! (não ou negação), e xor()
(ou exclusivo).
Tanto | quanto xor() retornarão TRUE se uma
ou outra comparação lógica retornar TRUE. xor() difere de
| porque retornará FALSE se ambas as comparações lógicas
retornarem TRUE. O nome xor significa ou
exclusivo.
Estude o diagrama abaixo para entender melhor como esses operadores funcionam.
## Error in knitr::include_graphics("images/transform-logical.png"): Cannot find the file(s): "images/transform-logical.png"
Teste seu Conhecimento
Erros comuns
Em R, a ordem das operações não funciona como no inglês. Você não
pode escrever
filter(diabetes, frame == 'medium' $ 'large'), mesmo que
você possa dizer “encontre todos pacientes medios e grandes”.
Certifique-se de escrever um teste completo em cada lado de um
operador booleano.
Aqui estão mais quatro dicas para ajudá-lo a usar testes lógicos e operadores booleanos em R:
- Um atalho útil para esse problema é
x %in% y. Isso selecionará todas as linhas ondexé um dos valores emy. Poderíamos usá-lo para reescrever o código na questão acima:
medium_large <- filter(diabetes, frame %in% c("medium", "large"))
- Às vezes, você pode simplificar subsetting complicado lembrando da
Lei de De Morgan:
!(x & y)é o mesmo que!x | !y!(x | y)é o mesmo que!x & !y.
Por exemplo, se você quisesse encontrar pacientes do sexo feminino (female) com biotipo grande (large) ou médio (medium), da podemos dizer que queremos os pacientes femininos que não sejam pequenos (small)
filter(diabetes, gender != "male" & frame != "small")
filter(diabetes, !(gender == "male" | frame == "small"))
Precisamos ter cuidado com um detalhe: ao filtramos que não é pequeno, incluímos no dataframe criado os pacientes que tem dados ausentes nessa variável.
- Assim como
&e|, o R também possui&&e||. Não use esses operadores comfilter()! Você aprenderá quando deve usá-los mais adiante.
- Sempre que começar a usar expressões complicadas e multipartes em
filter(), considere transformá-las em variáveis explícitas. Isso facilita muito a verificação do seu trabalho. Você aprenderá como criar novas variáveis em breve.
Valores ausentes
NA
Valores ausentes podem tornar comparações complicadas em R. O R usa
NA para representar valores ausentes ou desconhecidos. Os
NAs são “contagiosos” porque quase qualquer operação
envolvendo um valor desconhecido (NA) também será
desconhecida (NA). Por exemplo, você pode determinar a que
valor essas expressões que usam valores ausentes devem ser avaliadas?
Faça uma previsão e depois clique em “Enviar Resposta”.
NA > 5
10 == NA
NA + 10
NA / 2
NA == NA
is.na()
O código abaixo é o mais confuso de todos:
NA == NA
## [1] NA
“É mais fácil entender por que isso é verdade com um pouco mais de contexto:”
# Seja x a idade de Maria. Não sabemos quantos anos ela tem.
x <- NA
# Seja y a idade de João. Não sabemos quantos anos ele tem.
y <- NA
# João e Maria têm a mesma idade?
x == y
## [1] NA
# Não sabemos!
“Se você deseja determinar se um valor está ausente, use is.na():”
is.na(x)
## [1] TRUE
filter() and NAs
filter() inclui apenas as linhas onde a condição é TRUE;
ela exclui tanto os valores FALSE quanto os valores NA. Se você quiser
preservar os valores ausentes, solicite-os explicitamente:”
df <- tibble(x = c(1, NA, 3))
filter(df, x > 1)
filter(df, is.na(x) | x > 1)
Exercícios
Exercício 1
Use os blocos de código abaixo para encontrar todos os pacientes solicitados
- Filtre os pacientes diabéticos, ou seja, tem níveis de glicohemoglobina maiores do que 7.
filter(diabetes, glyhb > 7) #
Dica: Os níveis de glicohemoglobina estão na variável glyhb
- Filtre os pacientes com biotipos pequeno (small) e médio (medium)
filter(diabetes, frame %in% c("small", "medium"))
Hint: Este é um bom caso para o operador
%in%.
- Filtre os pacientes do sexo feminino do biotipo pequeno ou médio
filter(diabetes, gender == "female" & frame %in% c("small", "medium"))
Dica: gender == “female” & frame %in% c(“small”, “medium”).
- Filtre os pacientes do sexo masculino, da cidade de Louisa e diabéticos.
filter(diabetes, gender == "male" & glyhb > 7 & location == "Louisa")
Dica: gender == “male” & glyhb > 7 & location == “Louisa”.
- Quais pacientes diabéticos e com níveis de colesterol altos (>240)
filter(diabetes, glyhb > 7 & chol > 240)
Dica: glyhb > 7 & chol > 240.
- Filtre os pacientes com idade igual maior que 80 anos e diabeticos (glyhb >7)
filter(diabetes, glyhb >7 & age >= 80)
Dica: glyhb >7 & age >= 80
Exercise 2
Outro auxiliar de filtragem útil do dplyr é between(). O
que ele faz? Você pode usar between() para simplificar o
código necessário para responder aos desafios anteriores?
?between
- Filtre os pacientes entre 21 e 25 anos do sexo feminino, incluindo as idades de 21 e 25 anos
filter(diabetes, gender == "female" & between(age, 21, 25))
Dica: gender == “female” & between(age, 21, 25).
Exercise 3
Quantos pacientes têm um valores ausentes na medida da glicohemoglobina (glyhb)?filter(diabetes, is.na(glyhb))
Hint: Este é um bom caso para
is.na().
Exercise 4
Por que NA ^ 0 não é um valor ausente? Por que NA | TRUE não é ausente? Por que FALSE & NA não é ausente? Você consegue descobrir a regra geral? (NA * 0 é um contraexemplo complicado!)
# Qualquer número com um expoente zero é igual a um
NA ^ 0
# valor desconhecido ou verdadeiro avalia como verdadeiro
# (porque se um dos operandos de "ou" for verdadeiro, podemos ter certeza de que o resultado é verdadeiro)
NA | TRUE
# falso e valor desconhecido avalia como falso
# (porque se um dos operandos de "e" for falso, podemos ter certeza de que o resultado é falso)
FALSE & NA
# isso não é uma comparação lógica, é um cálculo numérico envolvendo um
# valor desconhecido, resultando assim em um valor desconhecido
NA * 0