Existem três tipos de operadores que podem ser usados para indexar (e selecionar) sub-conjuntos (subsets) de objetos no R:
[ ]
sempre retorna um objeto da mesma classe que o original. Pode ser usado para selecionar múltiplos elementos de um objeto[[ ]]
é usado para extrair elementos de uma lista ou data frame. Pode ser usado para extrair um único elemento, e a classe do objeto retornado não precisa necessariamente ser uma lista ou data frame.$
é usado para extrair elementos nomeados de uma lista ou data frame. É similar ao operador [[ ]]
.Observe o seguinte vetor de contagens
cont <- c(8, 4, NA, 9, 6, 1, 7, 9)
cont
[1] 8 4 NA 9 6 1 7 9
Para acessar o valor que está na posição 4, faça:
cont[4]
[1] 9
Os colchetes
[ ]
são utilizados para extração (seleção de um intervalo de dados) ou substituição de elementos. O valor dentro dos colchetes é chamado de índice.
Para acessar os valores nas posições 1, 4 e 8 é necessário o uso da função c()
:
cont[c(1, 4, 8)]
[1] 8 9 9
Ou:
ind <- c(1, 4, 8)
cont[ind]
[1] 8 9 9
Para selecionar todos os valores, excluindo aqueles das posições 1, 4 e 8:
cont[-c(1, 4, 8)]
[1] 4 NA 6 1 7
Também é possível selecionar uma sequência de elementos (com qualquer uma das funções de gerar sequências que já vimos antes):
## Seleciona os elementos de 1 a 5
cont[1:5]
[1] 8 4 NA 9 6
## Seleciona os elementos nas posições ímpar
cont[seq(1, 8, by = 2)]
[1] 8 NA 6 7
88, 5, 12, 13
Para selecionar todos os elementos que sejam NA
, ou todos menos os NA
s, precisamos usar a função is.na()
## Para selecionar os NAs
cont[is.na(cont)]
[1] NA
## Para selecionar todos menos os NAs
cont[!is.na(cont)]
[1] 8 4 9 6 1 7 9
Para substituir os NA
s por algum valor (e.g. 0):
cont[is.na(cont)] <- 0
cont
[1] 8 4 0 9 6 1 7 9
E para especificar NA
para algum valor
is.na(cont) <- 3
cont
[1] 8 4 NA 9 6 1 7 9
## Mais seguro do que
# cont[3] <- NA
Note que se utilizarmos o operador de atribuição
<-
em conjunto com uma indexação, estaremos substituindo os valores selecionados pelos valores do lado direito do operador de atribuição.
Quando vetores possuem seus componentes nomeados, a indexação pode ser realizada pelos nomes destes componentes.
## Atribui as letras "a", "b", ..., "h" para os componentes de cont
names(cont) <- letters[1:length(cont)]
## Acessando o quarto elemento
cont["d"]
d
9
## Acessando o sexto e o primeiro elemento
cont[c("f", "a")]
f a
1 8
Dica: veja
?letters
Considere a seguinte matriz
mat <- matrix(1:9, nrow = 3)
mat
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Acesse o valor que está na linha 2 da coluna 3:
mat[2, 3]
[1] 8
A indexação de matrizes sempre segue a ordem
[linha, coluna]
Para acessar todas as linhas da coluna 1:
mat[, 1]
[1] 1 2 3
Para acessar todas as colunas da linha 1:
mat[1, ]
[1] 1 4 7
Note que o resultado destas extrações trazem os valores internos das matrizes, mas com a dimensão reduzida (nestes casos para uma dimensão). Se o objetivo for, por exemplo, extrair uma parte da matriz, mas mantendo as duas dimensões, então precisamos usar o argumento drop
da “função” [
(sim, também é uma função; veja "?["
). Veja as diferenças:
mat[3, 2]
[1] 6
mat[3, 2, drop = FALSE]
[,1]
[1,] 6
mat[1, ]
[1] 1 4 7
mat[1, , drop = FALSE]
[,1] [,2] [,3]
[1,] 1 4 7
Para acessar as linhas 1 e 3 das colunas 2 e 3:
mat[c(1, 3), c(2, 3)]
[,1] [,2]
[1,] 4 7
[2,] 6 9
E note que aqui a dimensão já é 2 pois naturalmente o resultado preisa ser representado em duas dimensões.
Se as matrizes tiverem linhas e/ou colunas nomeados, a indexação também pode ser feita com os nomes.
##----------------------------------------------------------------------
## Nomes das colunas
colnames(mat) <- LETTERS[1:3]
## Todas as linhas da coluna B
mat[, "B"]
[1] 4 5 6
## Elemento da linha 1 e coluna C
mat[1, "C"]
C
7
##----------------------------------------------------------------------
## Nomes das linhas
rownames(mat) <- LETTERS[24:26]
## Todas as colunas da linha X
mat["X", ]
A B C
1 4 7
## Elemento da linha Y e coluna A
mat["Y", "A"]
[1] 2
Considere a seguinte lista:
lis <- list(c(3, 8, 7, 4), mat, 5:0)
lis
[[1]]
[1] 3 8 7 4
[[2]]
A B C
X 1 4 7
Y 2 5 8
Z 3 6 9
[[3]]
[1] 5 4 3 2 1 0
Para acessar o segundo componente da lista:
lis[[2]]
A B C
X 1 4 7
Y 2 5 8
Z 3 6 9
Para acessar o terceiro valor do primeiro componente:
lis[[1]][3]
[1] 7
Note que o segundo elemento da lista é uma matriz, portanto a indexação da matriz dentro da lista também segue o mesmo padrão
lis[[2]][2, 3]
[1] 8
Se a lista tiver componentes nomeados, eles podem ser acessados com o operador $
:
lis <- list(vetor1 = c(3, 8, 7, 4), mat = mat, vetor2 = 5:0)
## Ou
## names(lis) <- c("vetor1", "mat", "vetor2")
lis
$vetor1
[1] 3 8 7 4
$mat
A B C
X 1 4 7
Y 2 5 8
Z 3 6 9
$vetor2
[1] 5 4 3 2 1 0
## Acesando o segundo componente
lis$mat
A B C
X 1 4 7
Y 2 5 8
Z 3 6 9
## Linha 2 e coluna 3
lis$mat[2, 3]
[1] 8
## Terceiro elemento do primeiro componente
lis$vetor1[3]
[1] 7
Ou então
lis[["mat"]]
A B C
X 1 4 7
Y 2 5 8
Z 3 6 9
lis[["vetor1"]][3]
[1] 7
O símbolo
$
é utilizado para acessar componentes nomeados de listas ou data frames.
Considere o seguinte data frame
da <- data.frame(A = 4:1, B = c(2, NA, 5, 8))
da
A B
1 4 2
2 3 NA
3 2 5
4 1 8
Para acessar o segundo elemento da primeira coluna (segue a mesma lógica da indexação de matrizes pois também possui duas dimensões):
da[2, 1]
[1] 3
Acesse todas as linhas da coluna B:
da[, 2]
[1] 2 NA 5 8
Ou usando o nome da coluna:
da[,"B"]
[1] 2 NA 5 8
Todas as colunas da linha 1:
da[1, ]
A B
1 4 2
Ou usando o “nome” da linha:
da["1", ]
A B
1 4 2
Como o data frame é um caso particular de uma lista (onde todos os componentes tem o mesmo comprimento), as colunas de um data frame também podem ser acessadas com $
:
da$A
[1] 4 3 2 1
Para acessar o terceiro elemento da coluna B:
da$B[3]
[1] 5
Para acessar os elementos nas posições 2 e 4 da coluna B:
da$B[c(2, 4)]
[1] NA 8
Tamém é possível indexar data frames com
[[ ]]
assim como em listas, mas não é muito funcional.
Para lidar com NA
s em data frames, podemos também usar a função is.na()
da[is.na(da), ] # nao retorna o resultado esperado
A B
NA NA NA
## Deve ser feito por coluna
da[is.na(da$A), ]
[1] A B
<0 rows> (or 0-length row.names)
da[is.na(da$B), ]
A B
2 3 NA
## De maneira geral
is.na(da)
A B
[1,] FALSE FALSE
[2,] FALSE TRUE
[3,] FALSE FALSE
[4,] FALSE FALSE
is.na(da$A)
[1] FALSE FALSE FALSE FALSE
is.na(da$B)
[1] FALSE TRUE FALSE FALSE
Para remover as linhas que possuem NA
, note que será necessário remover todas as colunas daquela linha, pois data frames não podem ter colunas de comprimentos diferentes
da[!is.na(da$B), ]
A B
1 4 2
3 2 5
4 1 8
A função complete.cases()
facilita esse processo. Veja o resultado
complete.cases(da)
[1] TRUE FALSE TRUE TRUE
da[complete.cases(da), ]
A B
1 4 2
3 2 5
4 1 8
with()
Para evitar fazer muitas indexações de um mesmo data frame, por exemplo, podemos utilizar a função with()
with(da, A)
[1] 4 3 2 1
é o mesmo que
da$A
[1] 4 3 2 1
Também é útil para acessar elementos específicos dentro de data frames. Por exemplo, o terceiro elemento da coluna B
with(da, B[3])
[1] 5
$
), contendo 30 valores aleatórios de uma distribuição normal \(\text{N}(12, 4)\) (veja ?rnorm
)runif(7, 1, 5)
NA
s) existem nesse data frame?NA
s deste data frame.A
com os valores 1:5
, e B
com as letras de “a” a “f”A
B
## 1.
mm <- matrix(c(4, 10, 9, 2, 16, 5, 9, 0, 2, 11, 5, NA), nrow = 4)
## 2.
mm[4, 2]
## 3.
mm[-3, -2]
## 4.
ll <- list(v1 = 1:10, v2 = letters[1:7], mm = mm)
ll
## 5.
ll[[1]][5:3]
ll$v1[5:3]
## 6.
ll[[2]][-c(2,6)]
ll$v2[-c(2,6)]
## 7.
ll[[3]][, 3]
ll$mm[, 3]
## 8.
ll$v3 <- rnorm(30, mean = 12, sd = 2)
## 9.
dd <- data.frame(Letras = LETTERS[1:10],
Numeros = c(runif(7, 1, 5), rep(NA, 3)))
dd
## 10.
dd[1:2, ]
head(dd, 2)
## 11.
dd[9:10, ]
tail(dd, 2)
## 12.
dd[6, 1]
## 13.
dd[4, 2]
## 14.
sum(is.na(dd))
## 15.
dd <- dd[complete.cases(dd), ]
## 16.
dd$Nova <- 1:7
dd
## 17.
ll$l1 <- list(A = 1:5, B = letters[1:6])
ll
## 18.
ll$l1$A[4]
## 19.
ll$l1$B[3]
A seleção condicional serve para extrair dados que satisfaçam algum critério, usando expressões condicionais e operadores lógicos.
Considere o seguinte vetor
dados <- c(5, 15, 42, 28, 79, 4, 7, 14)
Selecione apenas os valores maiores do que 15:
dados[dados > 15]
[1] 42 28 79
Selecione os valores maiores que 15 E menores ou iguais a 35:
dados[dados > 15 & dados <= 35]
[1] 28
Para entender como funciona a seleção condicional, observe apenas o resultado da condição dentro do colchetes:
## Usando & (e)
dados > 15 & dados <= 35
[1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
## Usando | (ou)
dados > 15 | dados <= 35
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Os valores selecionados serão aqueles em que a condição for TRUE
, no primeiro caso apenas o quarto elemento do vetor dados
.
A seleção condicional também é muito útil para selecionar elementos de um vetor, baseado em uma condição de outro vetor.
Considere o seguinte vetor de caracteres
cara <- letters[1:length(dados)]
Considere que de alguma forma, os objetos dados
e cara
possuem alguma relação. Sendo assim, podemos selecionar elementos de dados
, baseados em alguma condição de cara
## Elemento de dados onde cara é igual a "c"
dados[cara == "c"]
[1] 42
Se quisermos selecionar mais de um elemento de dados
, baseado em uma condição de cara
?
## Elementos de dados onde cara é igual a "a" e "c"
cara == "a" & cara == "c" # porque não funciona?
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
cara == "a" | cara == "c"
[1] TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
dados[cara == "a" | cara == "c"]
[1] 5 42
Uma solução melhor seria se pudessemos usar
dados[cara == c("a", "c")]
[1] 5
mas nesse caso só temos o primeiro elemento. Um operador muito útil nestes casos é o %in%
dados[cara %in% c("a", "c")]
[1] 5 42
cara %in% c("a", "c")
[1] TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
Veja a diferença
cara == c("a", "c")
[1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
cara %in% c("a", "c")
[1] TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
Também é possível fazer a seleção de cara
, baseado em uma condição em dados
## Elemento de cara onde dados é igual a 15
cara[dados == 15]
[1] "b"
## Elemento de cara onde dados for maior do que 30
cara[dados > 30]
[1] "c" "e"
## Elemento de cara onde dados for igual a 4 ou 14
cara[dados %in% c(4, 14)]
[1] "f" "h"
which()
Até agora vimos seleções condicionais que nos retornavam o resultado de uma expressão condicional em vetores. No entanto, muitas vezes estamos interessados em saber a posição do resultado de uma expressão condicional, ao invés do resultado em si.
A fução which()
retorna as posições dos elementos que retornarem TRUE
em uma expressão condicional.
## Elementos maiores de 15
dados[dados > 15]
[1] 42 28 79
which(dados > 15)
[1] 3 4 5
## Elementos maiores de 15 e menores ou iguais a 35
dados[dados > 15 & dados <= 35]
[1] 28
which(dados > 15 & dados <= 35)
[1] 4
## Elementos de dados onde cara igual a "c"
dados[cara == "c"]
[1] 42
which(cara == "c")
[1] 3
## Elementos de dadaos onde cara igual a "a" ou "c"
dados[cara %in% c("a", "c")]
[1] 5 42
which(cara %in% c("a", "c"))
[1] 1 3
x
) com os valores 3, 8, 10, 4, 9, 7, 1, 9, 2, 4.a
) com as letras de A até JConsidere o seguinte data frame
dados <- data.frame(ano = c(2001, 2002, 2003, 2004, 2005),
captura = c(26, 18, 25, 32, NA),
porto = c("SP", "RS", "SC", "SC", "RN"))
Extraia deste objeto apenas a linha correspondente ao ano 2004:
dados[dados$ano == 2004, ]
ano captura porto
4 2004 32 SC
Mostre as linhas apenas do porto “SC”:
dados[dados$porto == "SC", ]
ano captura porto
3 2003 25 SC
4 2004 32 SC
Observe as linhas onde a captura seja maior que 20, selecionando apenas a coluna captura
:
dados[dados$captura > 20, "captura"]
[1] 26 25 32 NA
Também exclua as linhas com NA
s (agora com todas as colunas):
dados[dados$captura > 20 & !is.na(dados$captura), ]
ano captura porto
1 2001 26 SP
3 2003 25 SC
4 2004 32 SC
dados[dados$captura > 20 & complete.cases(dados), ]
ano captura porto
1 2001 26 SP
3 2003 25 SC
4 2004 32 SC
A condição pode ser feita com diferentes colunas:
dados[dados$captura > 25 & dados$porto == "SP", ]
ano captura porto
1 2001 26 SP
A função subset()
serve para os mesmos propósitos, e facilita todo o processo de seleção condicional:
dados[dados$porto == "SC", ]
ano captura porto
3 2003 25 SC
4 2004 32 SC
subset(dados, porto == "SC")
ano captura porto
3 2003 25 SC
4 2004 32 SC
dados[dados$captura > 20, ]
ano captura porto
1 2001 26 SP
3 2003 25 SC
4 2004 32 SC
NA NA NA <NA>
subset(dados, captura > 20)
ano captura porto
1 2001 26 SP
3 2003 25 SC
4 2004 32 SC
dados[dados$captura > 20 & !is.na(dados$captura), ]
ano captura porto
1 2001 26 SP
3 2003 25 SC
4 2004 32 SC
dados[dados$captura > 20, "captura"]
[1] 26 25 32 NA
subset(dados, captura > 20, select = captura)
captura
1 26
3 25
4 32
A grande vantagem é que a função subset()
já lida com os NA
s (se isso for o que você precisa).
A resolução de todos os exercícios desta página está disponível neste script.
Este conteúdo está disponível por meio da Licença Creative Commons 4.0