Universidade Federal de Pelotas. Departamento de Ecologia, Biologia e Genética
Você consegue entender as seguintes linhas de código?
cod 1
cod 2
cod 3
cod 4
cod 5
cod 6
cod 7
cod 8
Refere-se às regras que R usa para extrair ou isolar informações de cada estrutura de dados.
Baseadas em:
Atributos do objeto (comprimento, dimensões, nomes e tipo).
Posição dos elementos.
Condições nos elementos que o objeto contém.
R usa três símbolos pra a indexação: [], [[]] e $.
Rcharacter, logical, numeric (double, integer) y factor[8, 10, 3, 5]Indexação
vetor[elemento]vetor[[elemento]]Comprimento
Tipo
Nome
NULL pode ser entendido como nada, um conjunto vazio já que v1 ainda não tem nomes.
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
Agora vamos dar uma olhada nos atributos de v1
A primeira linha indica que v1 é um vetor de inteiros (int), com comprimento 10 ([1:10]) e nomes (attr(*, "names")), os quais são de tipo chr.
Podemos usar esses atributos para indexar os itens em v1.
Temos treis metodos:
vamos indexar o quinto elemento do vetor v1. Para fazer isso usamos [] o [[]], vamos ver o que isso implica
quando indexamos um objeto com [] o resultado é um subconjunto que herda atributos do objeto do qual foi extraído, neste caso o nome do quinto elemento (e).
[[]] é usado para enfatizar o elemento que você deseja indexar, sem considerar seus atributos no objeto.
Agora vamos indexar mais de um elemento pela sua posição, vejamos três opções:
Elementos consecutivos:
Elementos não consecutivos:
Por que usamos c()?
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
a
3
a f
3 9
<NA>
NA
Por que o resultado é NA?
Observe que, em essência, estamos usando um vetor do tipo caractere (os nomes de v1) para indexar os valores hospedados em v1. Então também poderíamos salvar os nomes de v1 em um novo objeto e usá-lo para indexar v1. Vamos ver:
Este exemplo nos ajuda a ilustrar dois pontos-chave para entender como o código do R funciona:
R executa o código de maneira aninhada. Ou seja, no código v1[nomes_v1[c(3:5, 9)]] a ordem de execução foi:c() agrupou os números 3 a 5 e 9 (ou seja, c (3:5, 9)):R usou esta sequência de números para indexar o vetor nomes_v1
R usou o vetor ['c', 'd', 'e', 'i'] para indexar v1:
É baseado no uso de operadores booleanos
Consiste em fazer “perguntas” com respostas binárias. Ou seja, usamos a sintaxe R para consultar se os elementos contidos em um objeto atendem ou não a uma determinada condição.
Vamos dar uma olhada nos principais operadores booleanos:
X == Y: igualX > Y: maior queX < Y: menor queX >= Y: maior ou igualX <= Y: menor ou igualX | Y: X ou YX & Y: X e Y!X: negação (ou seja, NÃO X)Podemos usá-los para fazer perguntas lógicas (ou seja, SIM ou NÃO, TRUE ou FALSE), por exemplo:
O resultado é um vetor booleano onde cada elemento corresponde às perguntas 5 > V1[1], …, 5 > V1[10]. Ou seja, R itera sobre cada elemento de v1 para realizar este ou qualquer tipo de operação. Isso é conhecido como vetorização.
Vamos usar esse vetor booleano para indexar v1, temos duas alternativas:
o
O resultado é um subconjunto contendo os elementos de v1 maiores que 5 (ou seja, aqueles que sao TRUE).
Podemos realizar operações mais complexas, combinando diferentes tipos de operadores booleanos
Isso é o que aconteceu
a b c d e f g h i j
3 10 2 8 6 9 1 7 5 4
a b c d e f g h i j
TRUE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE TRUE
a b c d e f g h i j
FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
c g
2 1
Algumas funções para explorar atributos dos vetores
character, logical, numeric y factor.Tipos do indexação:
vetor[1], vetor[[1]])vetor['nome'], vetor[['nome']])vetor[vetor condição valor])Matrices: são vetores com duas dimensões, linhas e colunas. Atributos: comprimento, linhas, colunas, nomes e tipo.
Indexação:
matriz[linha, coluna]matriz[[elemento]]
Usamos a função matrix() para criar as matrizes em R:
Vamos explorar o vetor v2 e ver como ele foi organizado em formato matriz
vetor:
matriz:
m contém um matriz de \(6 \times 5\).
Podemos explorar seus atributos com as funções length(), ncol(), nrow(), dim(), colnames(), rownames(), dimnames() e str(). Primeiro, vamos atribuir nomes às linhas e colunas e depois continuar com a indexação.
Indexação por posição:
C1 C2 C3 C4 C5
F1 8 11 10 6 6
F2 9 5 8 8 8
F3 14 4 15 6 5
F4 10 13 11 8 12
F5 10 11 3 4 12
F6 15 11 7 6 12
C1 C2 C3 C4 C5
F1 8 11 10 6 6
F2 9 5 8 8 8
F3 14 4 15 6 5
F4 10 13 11 8 12
C1 C2 C3 C5
F3 14 4 15 5
F4 10 13 11 12
F5 10 11 3 12
F6 15 11 7 12
Indexação por nome:
C1 C2 C3 C4 C5
F1 8 11 10 6 6
F2 9 5 8 8 8
F3 14 4 15 6 5
F4 10 13 11 8 12
F5 10 11 3 4 12
F6 15 11 7 6 12
nom_fila <- rownames(m)
nom_col <- colnames(m)
m[nom_fila[c(1:3, nrow(m))], nom_col[ncol(m)]] # indexando linhas e colunasF1 F2 F3 F6
6 8 5 12
Você entende esse código?
Indexação por condição:
Coisas a ter em mente:
Não indicar nenhum índice no espaço de linhas ou colunas significa que nada está indexado naquela dimensão (m[1:3, ]).
Quando a indexação resulta em elementos de uma única dimensão (linha ou coluna), R por defeito reduz a matriz em um vetor
Se indexarmos a primeira linha da matriz, teremos:
Para evitar essa redução na dimensionalidade da matriz, usamos o argumento drop = FALSE entre colchetes da indexação.
Algumas funções para explorar atributos da matriz
character, logical, numeric y factor.Indexação:
matriz[linhas, colunas]
\(\rightarrow\)
Os arrays são matrizes de \(i \times j\) organizadas em N dimensões. As dimensões implicam basicamente uma série de matrizes aninhadas hierarquicamente,
R usa "," para denotar cada aninhamento na indexação.
array[linha, coluna, aninhamento 1, ... , aninhamento N]
Vamos criar o vetor v3 e ver como agrupá-lo com a função array().
num [1:6, 1:5, 1:2, 1:2, 1:3] 7 8 35 14 23 9 21 32 35 29 ...
- attr(*, "dimnames")=List of 5
..$ : chr [1:6] "F1" "F2" "F3" "F4" ...
..$ : chr [1:5] "C1" "C2" "C3" "C4" ...
..$ : chr [1:2] "ani_1a" "ani_1b"
..$ : chr [1:2] "ani_2a" "ani_2b"
..$ : chr [1:3] "ani_3a" "ani_3b" "ani_3c"
Indexação por posição:
Indexação por nome:
, , ani_2a, ani_3a
C1 C2 C3 C4 C5
F1 7 21 15 13 13
F2 8 32 26 16 15
F3 35 35 37 25 11
F4 14 29 9 14 18
F5 23 21 3 10 9
F6 9 10 17 10 16
, , ani_2b, ani_3a
C1 C2 C3 C4 C5
F1 15 26 17 15 17
F2 18 28 19 15 21
F3 41 14 7 18 13
F4 33 16 12 14 35
F5 46 9 53 6 22
F6 7 18 27 15 8
, , ani_2a, ani_3b
C1 C2 C3 C4 C5
F1 19 34 21 47 26
F2 32 22 14 13 8
F3 28 3 15 15 20
F4 59 45 39 43 42
F5 61 8 15 11 43
F6 18 20 21 9 32
, , ani_2b, ani_3b
C1 C2 C3 C4 C5
F1 19 9 13 12 12
F2 18 11 7 34 20
F3 20 11 15 10 28
F4 10 27 16 10 21
F5 11 10 29 28 19
F6 28 37 23 13 25
, , ani_2a, ani_3c
C1 C2 C3 C4 C5
F1 8 6 27 14 10
F2 27 9 14 25 12
F3 14 8 12 9 9
F4 28 11 6 30 22
F5 3 13 15 13 7
F6 29 7 3 20 33
, , ani_2b, ani_3c
C1 C2 C3 C4 C5
F1 35 12 16 17 5
F2 16 17 70 19 26
F3 7 20 7 15 40
F4 35 21 53 13 15
F5 21 22 8 4 16
F6 9 38 8 20 10
Quando usamos arrays?
É útil quando tratamos dados do mesmo tipo com uma estrutura aninhada, por exemplo:
imagine um conjunto de dados em que cada linha corresponde a um indivíduo, cada coluna a uma característica funcional, o primeiro aninhamento corresponde a fragmentos florestais, o segundo às paisagens e o terceiro às ecorregiões.
character, logical, numeric y factor.Indexação:
array[linhas, colunas, dimensão 1, ... , dimensão N]
data frames (tibbles): são usados para armazenar estrutura de dados tabulares. As colunas podem ser de tipos diferentes, mas devem ter o mesmo comprimento
Atributos: comprimento, linhas, colunas, nomes.
Indexação
data_frame[linha, coluna]data_frame[[coluna]]data_frame[coluna]Os data frames e tibbles são utilizados para armazenar conjuntos de dados relacionais onde as colunas correspondem a variáveis (diferentes tipos) e as linhas correspondem a casos ou observações. e.g. \(\rightarrow\)
| obs | ind | sp | peso |
|---|---|---|---|
| 1 | 1 | sp1 | 10.39 |
| 2 | 2 | sp1 | 9.98 |
| 3 | 1 | sp2 | 11.29 |
| 4 | 2 | sp2 | 7.97 |
| 5 | 1 | sp3 | 11.30 |
| 6 | 2 | sp3 | 8.66 |
Data frames vs tibbles
Os data frames vêm por defeito com a instalação do R. tibble::tibble.
Visualizando dos dados no console.
Os tibbles são melhores para aninhar listas em colunas.
Lembra do argumento drop? Por defeito, ele está definido como FALSE nos tibbles. Portanto, enquanto data_frame[, 1] resulta em um vetor da coluna 1, tibble[, 1] gera um tibble (ou tabela) de \(N~rows \times 1\).
A sintaxe para criar os dois tipos de objetos. A condição é que os vetores (ou seja, colunas) tenham o mesmo comprimento.
tibbles:
data frames:
data frame:
tibble:
diferenças do output no console:
data frame:
site trap formigas
1 bosque1 1 9
2 bosque1 1 18
3 bosque1 2 14
4 bosque1 2 4
5 bosque1 3 9
6 bosque1 3 17
7 bosque1 4 10
8 bosque1 4 9
9 bosque1 5 4
10 bosque1 5 2
11 bosque2 1 4
12 bosque2 1 2
13 bosque2 2 14
14 bosque2 2 1
15 bosque2 3 11
16 bosque2 3 4
17 bosque2 4 10
18 bosque2 4 9
19 bosque2 5 22
20 bosque2 5 17
21 bosque3 1 1
22 bosque3 1 14
23 bosque3 2 11
24 bosque3 2 5
25 bosque3 3 17
26 bosque3 3 11
27 bosque3 4 11
28 bosque3 4 12
29 bosque3 5 10
30 bosque3 5 3
tibble:
Indexação
Vejamos seis maneiras de indexar a mesma coluna do objeto tib:
[1] "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1"
[8] "bosque1" "bosque1" "bosque1" "bosque2" "bosque2" "bosque2" "bosque2"
[15] "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque3"
[22] "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3"
[29] "bosque3" "bosque3"
Na indexação do tibbles o símbolo [[]] é usado para extrair uma coluna por seu nome (formulário 3) ou sua posição (formulários 4 e 5).
[1] "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1"
[8] "bosque1" "bosque1" "bosque1" "bosque2" "bosque2" "bosque2" "bosque2"
[15] "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque3"
[22] "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3"
[29] "bosque3" "bosque3"
Na indexação do tibbles o símbolo [[]] é usado para extrair uma coluna por seu nome (formulário 3) ou sua posição (formulários 4 e 5).
[1] "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1"
[8] "bosque1" "bosque1" "bosque1" "bosque2" "bosque2" "bosque2" "bosque2"
[15] "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque3"
[22] "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3"
[29] "bosque3" "bosque3"
Neste caso o código é lido da esquerda para a direita: (i) indexamos a primeira coluna do tib (tib[, 1]), (ii) depois extraímos a primeira coluna em formato de vetor ([[1]])
[1] "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1" "bosque1"
[8] "bosque1" "bosque1" "bosque1" "bosque2" "bosque2" "bosque2" "bosque2"
[15] "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque2" "bosque3"
[22] "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3" "bosque3"
[29] "bosque3" "bosque3"
Neste caso o código é lido da esquerda para a direita: (i) indexamos a primeira coluna do tib (tib[, 1]), (ii) depois extraímos a primeira coluna em formato de vetor ([[1]]).
Veremos a filtragem de data frames ou tibbles e sua exploração na segunda parte do módulo.
Indexação:
data frame[linhas, colunas]
tibble[linhas, colunas]
As listas são a estrutura de dados mais flexiveis no R. Você pode imaginá-los como caixas onde qualquer coisa pode ser armazenada: vetores, matrizes, arrays, data frames, funções, outras listas.
Atributos: comprimento, nomes, tipo (dos elementos).
Indexação:
lista[elemento]
lista[[elemento]][objeto]
lista$nome_objeto[objeto]
Criamos listas com a função list().
O objeto l1 é uma lista vazia. Agora vamos armazenar diferentes objetos usando o símbolo $:
vamos dar uma olhada na estrutura de l1 \(\rightarrow\)
List of 4
$ vector: Named int [1:10] 3 10 2 8 6 9 1 7 5 4
..- attr(*, "names")= chr [1:10] "a" "b" "c" "d" ...
$ matriz: int [1:6, 1:5] 8 9 14 10 10 15 11 5 4 13 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:6] "F1" "F2" "F3" "F4" ...
.. ..$ : chr [1:5] "C1" "C2" "C3" "C4" ...
$ array : num [1:6, 1:5, 1:2, 1:2, 1:3] 7 8 35 14 23 9 21 32 35 29 ...
..- attr(*, "dimnames")=List of 5
.. ..$ : chr [1:6] "F1" "F2" "F3" "F4" ...
.. ..$ : chr [1:5] "C1" "C2" "C3" "C4" ...
.. ..$ : chr [1:2] "ani_1a" "ani_1b"
.. ..$ : chr [1:2] "ani_2a" "ani_2b"
.. ..$ : chr [1:3] "ani_3a" "ani_3b" "ani_3c"
$ tibble: tibble [30 × 3] (S3: tbl_df/tbl/data.frame)
..$ site : chr [1:30] "bosque1" "bosque1" "bosque1" "bosque1" ...
..$ trap : num [1:30] 1 1 2 2 3 3 4 4 5 5 ...
..$ formigas: num [1:30] 9 18 14 4 9 17 10 9 4 2 ...
tibble [30 × 3] (S3: tbl_df/tbl/data.frame)
$ site : chr [1:30] "bosque1" "bosque1" "bosque1" "bosque1" ...
$ trap : num [1:30] 1 1 2 2 3 3 4 4 5 5 ...
$ formigas: num [1:30] 9 18 14 4 9 17 10 9 4 2 ...
Observe que com o uso de $ armazenamos objetos e seus nomes:
As listas são uma estrutura de dados com uma única dimensão:
indexação
Ocorre em duas etapas e segue a mesma sintaxe que utilizamos para vetor \(\rightarrow\)
Usamos nomes ou posições para indexar cada objeto da lista:
e.g.
lista['nome 1']lista[1]lista[c('nome 1', 'nome 2')]lista[1:2]Poderíamos indexar por condição, mas precisamos iterar sobre os elementos da lista
(e.g. lapply(lista, is.matrix)).
Indexando um objeto (passo 1):
$vector
a b c d e f g h i j
3 10 2 8 6 9 1 7 5 4
$vector
a b c d e f g h i j
3 10 2 8 6 9 1 7 5 4
$matriz
C1 C2 C3 C4 C5
F1 8 11 10 6 6
F2 9 5 8 8 8
F3 14 4 15 6 5
F4 10 13 11 8 12
F5 10 11 3 4 12
F6 15 11 7 6 12
$tibble
# A tibble: 30 × 3
site trap formigas
<chr> <dbl> <dbl>
1 bosque1 1 9
2 bosque1 1 18
3 bosque1 2 14
4 bosque1 2 4
5 bosque1 3 9
6 bosque1 3 17
7 bosque1 4 10
8 bosque1 4 9
9 bosque1 5 4
10 bosque1 5 2
# … with 20 more rows
Devemos prestar especial atenção ao uso de [] ou [[]]. Por exemplo, sabemos que o segundo objeto de l1 é uma matriz Se indexarmos, deveremos ter um objeto com classe matrix, certo? Bem, depende:
l1[2] resulta em uma lista porque este tipo de indexação envolve um “corte” da lista, não extração do objeto em questão. Em vez disso, l1[[2]] enfatiza a extração do objeto.
list[[object]], passo 1) e, em seguida, usamos a indexação correspondente para extrair os elementos do objeto (list[[object]][indexing object], passo 2):Passo 1
Passo 2
Indexando o elemento na quarta posição (tibble)
As listas podem armazenar outras listas. Pra indexar só temos que prestar atenção na sequência do aninhamento, vejamos um exemplo:
Indexação:
lista[objeto]
lista[[objeto]][indexação do objeto]
lista$nome_objeto[indexação do objeto]