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  9Para acessar o valor que está na posição 4, faça:
cont[4][1] 9Os 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 9Ou:
ind <- c(1, 4, 8)
cont[ind][1] 8 9 9Para selecionar todos os valores, excluindo aqueles das posições 1, 4 e 8:
cont[-c(1, 4, 8)][1]  4 NA  6  1  7També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  788, 5, 12, 13Para selecionar todos os elementos que sejam NA, ou todos menos os NAs, 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 9Para substituir os NAs por algum valor (e.g. 0):
cont[is.na(cont)] <- 0
cont[1] 8 4 0 9 6 1 7 9E 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] <- NANote 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    9Acesse o valor que está na linha 2 da coluna 3:
mat[2, 3][1] 8A indexação de matrizes sempre segue a ordem
[linha, coluna]
Para acessar todas as linhas da coluna 1:
mat[, 1][1] 1 2 3Para acessar todas as colunas da linha 1:
mat[1, ][1] 1 4 7Note 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] 6mat[3, 2, drop = FALSE]     [,1]
[1,]    6mat[1, ][1] 1 4 7mat[1, , drop = FALSE]     [,1] [,2] [,3]
[1,]    1    4    7Para 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    9E 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] 2Considere 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 0Para acessar o segundo componente da lista:
lis[[2]]  A B C
X 1 4 7
Y 2 5 8
Z 3 6 9Para acessar o terceiro valor do primeiro componente:
lis[[1]][3][1] 7Note 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] 8Se 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] 7Ou então
lis[["mat"]]  A B C
X 1 4 7
Y 2 5 8
Z 3 6 9lis[["vetor1"]][3][1] 7O 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  8Para 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] 3Acesse todas as linhas da coluna B:
da[, 2][1]  2 NA  5  8Ou usando o nome da coluna:
da[,"B"][1]  2 NA  5  8Todas as colunas da linha 1:
da[1, ]  A B
1 4 2Ou usando o “nome” da linha:
da["1", ]  A B
1 4 2Como 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 1Para acessar o terceiro elemento da coluna B:
da$B[3][1] 5Para acessar os elementos nas posições 2 e 4 da coluna B:
da$B[c(2, 4)][1] NA  8Tamém é possível indexar data frames com
[[ ]]assim como em listas, mas não é muito funcional.
Para lidar com NAs 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 FALSEis.na(da$A)[1] FALSE FALSE FALSE FALSEis.na(da$B)[1] FALSE  TRUE FALSE FALSEPara 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 8A função complete.cases() facilita esse processo. Veja o resultado
complete.cases(da)[1]  TRUE FALSE  TRUE  TRUEda[complete.cases(da), ]  A B
1 4 2
3 2 5
4 1 8with()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 1També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)NAs) existem nesse data frame?NAs deste data frame.A com os valores 1:5, e B com as letras de “a” a “f”AB## 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 79Selecione os valores maiores que 15 E menores ou iguais a 35:
dados[dados > 15 & dados <= 35][1] 28Para 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 TRUEOs 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] 42Se 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 FALSEcara == "a" | cara == "c"[1]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSEdados[cara == "a" | cara == "c"][1]  5 42Uma solução melhor seria se pudessemos usar
dados[cara == c("a", "c")][1] 5mas nesse caso só temos o primeiro elemento. Um operador muito útil nestes casos é o %in%
dados[cara %in% c("a", "c")][1]  5 42cara %in% c("a", "c")[1]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSEVeja a diferença
cara == c("a", "c")[1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSEcara %in% c("a", "c")[1]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSETambé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 79which(dados > 15)[1] 3 4 5## Elementos maiores de 15 e menores ou iguais a 35
dados[dados > 15 & dados <= 35][1] 28which(dados > 15 & dados <= 35)[1] 4## Elementos de dados onde cara igual a "c"
dados[cara == "c"][1] 42which(cara == "c")[1] 3## Elementos de dadaos onde cara igual a "a" ou "c"
dados[cara %in% c("a", "c")][1]  5 42which(cara %in% c("a", "c"))[1] 1 3x) 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    SCMostre as linhas apenas do porto “SC”:
dados[dados$porto == "SC", ]   ano captura porto
3 2003      25    SC
4 2004      32    SCObserve as linhas onde a captura seja maior que 20, selecionando apenas a coluna captura:
dados[dados$captura > 20, "captura"][1] 26 25 32 NATambém exclua as linhas com NAs (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    SCdados[dados$captura > 20 & complete.cases(dados), ]   ano captura porto
1 2001      26    SP
3 2003      25    SC
4 2004      32    SCA condição pode ser feita com diferentes colunas:
dados[dados$captura > 25 & dados$porto == "SP", ]   ano captura porto
1 2001      26    SPA 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    SCsubset(dados, porto == "SC")   ano captura porto
3 2003      25    SC
4 2004      32    SCdados[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    SCdados[dados$captura > 20 & !is.na(dados$captura), ]   ano captura porto
1 2001      26    SP
3 2003      25    SC
4 2004      32    SCdados[dados$captura > 20, "captura"][1] 26 25 32 NAsubset(dados, captura > 20, select = captura)  captura
1      26
3      25
4      32A grande vantagem é que a função subset() já lida com os NAs (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