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 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]
## Toas as linhas da colua 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
## É necessário especificar as colunas
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
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
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
, nesse 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 dadaos 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).
Este conteúdo está disponível por meio da Licença Creative Commons 4.0