2.6 Vetores e operadores lógicos

Para manipular dados no R, entender vetores lógicos e operadores lógicos é fundamental. Vetores lógicos são vetores de verdadeiros (TRUE ou apenas T, sempre em letras maiúsculas) ou falsos (FALSE ou F). Eles podem ser convertidos em vetores numéricos e, portanto, operados matematicamente (T = 1, e F = 0).

2.6.1 Fazendo perguntas à vetores

Vetores lógicos podem ser respostas às perguntas feitas por operadores lógicos:

  • > - é maior que?

  • < - é menor que?

  • >= - é maior igual a?

  • <= - é menor igual a?

  • == - é igual a?

  • != - é diferente de?

  • %in% - compara conteúdo de vetores

Há ainda a função duplicated() que busca valores repetidos em um vetor. O resultado desta função é um vetor contendo TRUE ou FALSE. Valores que possuam o valor TRUE são duplicados. Para checar os duplicados, devemos filtrar o resultado desta ação (veja na seção 2.6.2).

# um vetor numerico
v1 <- 1:20
# quais valores de v1 são maiores ou iguais a 10
p1 <- v1 >= 10 # vai retornar um vetor lógico
p1
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE
## [13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# soma dos verdadeiros responde "quantos valores de v1 são maiores ou iguais a 10, pois apenas esses valores são verdadeiros ou seja são 1)
sum(p1)
## [1] 11
# experimente os demais operadores

# a regra da reciclagem também se aplica neste conceito
v1 <- 1:20
v2 <- 1:20
p2 <- v1 == v2 # compara cada par dos vetores que são idênticos
p2 # é o vetor lógico resultando, todos os valores são verdadeiros
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [16] TRUE TRUE TRUE TRUE TRUE
# portanto, as seguintes expressões também são verdadeiras
sum(v1 == v2) == length(v1)
## [1] TRUE
# ou então
sum(v1 == v2) == length(v2)
## [1] TRUE
# valores duplicados
vv <- c(2, 2, 2, 3, 4, 5)
vv # apenas o dois é duplicado
## [1] 2 2 2 3 4 5
duplicated(vv) # note que esta função retorna TRUE apenas para dois dos três valores 2 (o primeiro não é duplicado)
## [1] FALSE  TRUE  TRUE FALSE FALSE FALSE
# comparando vetores
v1 <- c(1, 2, 3, 4)
v2 <- c(4, 4, 5, 6)
v1 %in% v2 # quantos elementos de v1 existem em v2
## [1] FALSE FALSE FALSE  TRUE
sum(v1 %in% v2) # apenas 1
## [1] 1
v2 %in% v1 # quais elementos de v2 estão em v1
## [1]  TRUE  TRUE FALSE FALSE
sum(v2 %in% v1) # os dois quatro
## [1] 2
notas.dos.alunos <- c(6.0, 5.1, 6.8, 2.8, 6.1, 9.0, 4.3, 10.4, 6.0, 7.9, 8.9, 6.8, 9.8, 4.6, 11.3, 8.0, 6.7, 4.5)
## Quantos aprovados?
sum(notas.dos.alunos >= 5)
## [1] 14
# Qual a proporção de aprovados?
prop <- sum(notas.dos.alunos >= 5) / length(notas.dos.alunos)
prop
## [1] 0.7777778
# ou em texto
paste(round(prop * 100), "%", sep = "")
## [1] "78%"

Podemos usar também vetores de texto e fatores em conjunto com operadores lógicos.

# E VETORES DE TEXTO?
v1 <- rep(c("banana", "pera", "laranja", "limão"), 10)
v1 # um vetor de palavras
##  [1] "banana"  "pera"    "laranja" "limão"   "banana"  "pera"    "laranja"
##  [8] "limão"   "banana"  "pera"    "laranja" "limão"   "banana"  "pera"   
## [15] "laranja" "limão"   "banana"  "pera"    "laranja" "limão"   "banana" 
## [22] "pera"    "laranja" "limão"   "banana"  "pera"    "laranja" "limão"  
## [29] "banana"  "pera"    "laranja" "limão"   "banana"  "pera"    "laranja"
## [36] "limão"   "banana"  "pera"    "laranja" "limão"
# quantos elementos são iguais a banana
v1 == "banana"
##  [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [13]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [25]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [37]  TRUE FALSE FALSE FALSE
sum(v1 == "banana")
## [1] 10
# também poderia perguntar: quantos elementos de v1 contém banana
sum(v1 %in% "banana")
## [1] 10
v1 %in% "banana"
##  [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [13]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [25]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [37]  TRUE FALSE FALSE FALSE
# no caso acima == e %in% funcionam igual, mas o operador %in% é util quando quisermos comparar dois vetores de character
v2 <- c("banana", "pera", "abacate")
v1 %in% v2 # quais elementos de v1 correspondem a elementos de v2
##  [1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [13]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [25]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [37]  TRUE  TRUE FALSE FALSE
sum(v1 %in% v2) # quantos são? 10 laranjas e 10 peras
## [1] 20
v2 %in% v1 # quais elementos de v2 estão em v1
## [1]  TRUE  TRUE FALSE
sum(v2 %in% v1) # quantos são (apenas laranja e pera, abacate não está)
## [1] 2

Operadores auxiliares permitem combinar perguntas:

  • & equivale a E - essa condição E essa outra;

  • | equivale a OU - essa condição OU essa outra;

  • ! - inverte os valores da pergunta

# um vetor
v1 <- 1:20
v1
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
p1 <- v1 > 5 & v1 <= 15 # quais elementos de v1 são maiores que 5 E menores ou iguais a 15
sum(p1) # quantos são?
## [1] 10
p1 <- v1 > 5 | v1 <= 15 # quais elementos de v1 são maiores que 5 OU menores ou iguais a 15
sum(p1) # quantos são
## [1] 20
# !exclamação NEGA ou INVERTE verdadeiros e falsos
v1 <- 1:20
sum(v1 == 5) # quantos v1 são iguais a 5?
## [1] 1
sum(!v1 == 5) # quantos v1 são diferentes de 5?
## [1] 19
sum(v1 > 5) # quantos v1 são maiores que 5?
## [1] 15
sum(!v1 > 5) # quantos v1 são menores que 5?
## [1] 5
# texto
v1 <- rep(c("banana", "pera", "laranja", "limão"), 10)
v1 # um vetor de palavras
##  [1] "banana"  "pera"    "laranja" "limão"   "banana"  "pera"    "laranja"
##  [8] "limão"   "banana"  "pera"    "laranja" "limão"   "banana"  "pera"   
## [15] "laranja" "limão"   "banana"  "pera"    "laranja" "limão"   "banana" 
## [22] "pera"    "laranja" "limão"   "banana"  "pera"    "laranja" "limão"  
## [29] "banana"  "pera"    "laranja" "limão"   "banana"  "pera"    "laranja"
## [36] "limão"   "banana"  "pera"    "laranja" "limão"
vl <- v1 == "banana" & v1 == "pera" # quantos elementos de v1 sao banana E sao pera
vl
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [37] FALSE FALSE FALSE FALSE
sum(vl) # nenhum valor satisfaz as duas condicoes
## [1] 0
vl <- v1 == "banana" | v1 == "pera" # quantos elementos de v1 sao banana ou sao pera
vl
##  [1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [13]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [25]  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [37]  TRUE  TRUE FALSE FALSE
sum(vl) # tem 20 valores que satisfazem 1 das condições
## [1] 20
# isso é o mesmo que pergunta desse outro jeito:
sum(v1 %in% c("banana", "pera"))
## [1] 20

2.6.2 Filtrando dados com vetores lógicos

Vetores lógicos podem ser usados como índices (Seção 2.5) para filtrar elementos de um vetor. É através deste conceito que podemos filtrar dados de matrizes e criar subconjunto de dados.

# um vetor com sequencia de 1 a 100
v1 <- 1:100

p1 <- v1 > 15 # Pergunta 1 quantos são maiores que 15
v1[p1] # valores que satisfazem a pergunta 1
##  [1]  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34
## [20]  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53
## [39]  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72
## [58]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91
## [77]  92  93  94  95  96  97  98  99 100
p2 <- v1 <= 20 # Pergunta 2 quantos são menores ou iguais a 20
v1[p2] # valores que satisfazem a pergunta 2
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
# quantos satisfazem as duas perguntas
p3 <- p1 & p2
v1[p2] # valores que satisfazem as duas perguntas
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

A função grep() permite a busca de uma palavra (ou pedaço dela) em um vetor de palavras. Mais de uma palavra pode ser buscada ao mesmo tempo.

?grep # veja o help dessa função e seus argumentos
# um vetor de palavras
v1 <- rep(c("banana", "pera", "laranja", "limão"), 5)
grep("an", v1) # quais elementos tem a palavra 'an' no nome?
##  [1]  1  3  5  7  9 11 13 15 17 19
# note que é case.sensitive (depende se é maiusculo ou minúsculo)
grep("An", v1) # não encontra nada
## integer(0)
grep("An", v1, ignore.case = T) # mas eu posso dizer para ele ignorar se é minusculo ou maiúsculo e ele encontra novamente
##  [1]  1  3  5  7  9 11 13 15 17 19
# quem sao esses elementos
vl <- grep("An", v1, ignore.case = T) # pega os índices desses elementos
v1[vl]
##  [1] "banana"  "laranja" "banana"  "laranja" "banana"  "laranja" "banana" 
##  [8] "laranja" "banana"  "laranja"
unique(v1[vl]) # valores únicos desse vetor
## [1] "banana"  "laranja"

2.6.3 Perguntando por valores ausentes - NA

Vimos anteriormente como o R codifica valores ausentes (seção 1.8.4): converte em uma classe lógica definida pela palavra NA em maiúsculo. E nossos dados frequentemente têm valores ausentes. Isso vai gerar avisos indesejáveis e impedir certas análises. Então, muitas vezes precisamos tirar registros com valores ausentes ou colunas com muitos valores ausentes.

Perguntar por valores ausentes no R é feito por uma função especial chamada is.na(). A resposta da função é um vetor lógico indicando quem é e quem não é NA. Há uma outra função chamada na.omit() que elimina valores NA de um vetor.

?is.na # veja o help
# um vetor com NAs
v1 <- c(NA, NA, 1, 2, 3, 4, 5, 6)
is.na(v1) # quem é NA?
## [1]  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
v2 <- v1[!is.na(v1)] # criar um vetor novo com quem não é NA (note o !)
v2
## [1] 1 2 3 4 5 6
# isso também pode ser feito com na.omit()
?na.omit # veja o help dessa função
v3 <- na.omit(v1)
v3 # a diferença é que criou um objeto de classe na.omit
## [1] 1 2 3 4 5 6
## attr(,"na.action")
## [1] 1 2
## attr(,"class")
## [1] "omit"
v3 <- as.vector(v3) # isso elimina a diferença, convertendo em vetor
v3 # agora é idêntico a v2
## [1] 1 2 3 4 5 6
# agora suponha o seguinte vetor
v4 <- c("NA", "NA", "pera", "banana", "mamão")
is.na(v4) # ops todos são falsos
## [1] FALSE FALSE FALSE FALSE FALSE
# isso porque "NA" é texto e não um objeto de classe lógica
class(NA)
## [1] "logical"
class("NA")
## [1] "character"
# mas eu poderia corrigir isso
v4[v4 == "NA"] # vejo
## [1] "NA" "NA"
v4[v4 == "NA"] <- NA # corrijo
v4
## [1] NA       NA       "pera"   "banana" "mamão"
is.na(v4) # agora dois são NAs
## [1]  TRUE  TRUE FALSE FALSE FALSE
# note que agora todos são diferentes de "NA" como texto
v4[!v4 == "NA"]
## [1] NA       NA       "pera"   "banana" "mamão"
# mas isso de mostra quem não é corretamente
v5 <- v4[!is.na(v4)]
v5
## [1] "pera"   "banana" "mamão"