Estruturas de dados e indexação no R

Universidade Federal de Pelotas. Departamento de Ecologia, Biologia e Genética

Andrés F. Ramírez-Mejía, PhD

Dinâmica da aula

  • Muito texto na apresentação (será para você)
  • O que espero de você?
  • O que você pode esperar de mim?
  • Como será nossa comunicação?

Antes de começar:

Você consegue entender as seguintes linhas de código?

cod 1

1:5

cod 2

c(1, 2, 3, 4, 5)

cod 3

c(1:5, 7, 9, 9.5)

cod 4

v <- c(1, 2, 3, 4, 5)

cod 5

v <- c(1, 2, 3, 4, 5)
v[3]
v[[3]]

cod 6

v[c(3, 5)]

cod 7

v <- c(1, 2, 3, 4, 5)
v[3, 5]

cod 8

v <- c(1, 2, 3, 4, 5)
names(v) <- c('a', 'b', 'c', 'd', 'e')
v[names(v)[1]]
v['a']

Indexação

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 $.

Vetores

O que são vetores

  • Unidade primária de armazenamento de informações em R
  • Tipos: character, logical, numeric (double, integer) y factor
  • Eles têm apenas uma dimensão: comprimento. por exemplo. [8, 10, 3, 5]

Indexação

  • vetor[elemento]
  • vetor[[elemento]]

Vamos explorar seus atributos

set.seed(123)
v1 <- sample(1:10)

Comprimento

length(v1)
[1] 10

Tipo

class(v1)
[1] "integer"

Nome

names(v1)
NULL

NULL pode ser entendido como nada, um conjunto vazio já que v1 ainda não tem nomes.

names(v1) <- c('a', 'b', 'c', 'd', 'e', 
               'f', 'g', 'h', 'i', 'j')
names(v1)
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"


Agora vamos dar uma olhada nos atributos de v1


str(v1)
 Named int [1:10] 3 10 2 8 6 9 1 7 5 4
 - attr(*, "names")= chr [1:10] "a" "b" "c" "d" ...


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:

  • Indexação por posição
  • Indexação por nome
  • indexação por condição

Indexação por posição

vamos indexar o quinto elemento do vetor v1. Para fazer isso usamos [] o [[]], vamos ver o que isso implica

v1[5]
e 
6 
v1[[5]]
[1] 6

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:

v1[3:7]
c d e f g 
2 8 6 9 1 

Elementos não consecutivos:

v1[c(1, 3:5, 8)]
a c d e h 
3 2 8 6 7 

Por que usamos c()?

v1[1, 3:5, 8]
Error in v1[1, 3:5, 8]: incorrect number of dimensions

Indexação por nome

names(v1)
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
v1['a']
a 
3 
v1[c('a', 'f')]
a f 
3 9 
v1['z']
<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:


nomes_v1 <- names(v1)

v1[nomes_v1[c(3:5, 9)]]
c d e i 
2 8 6 5 

Este exemplo nos ajuda a ilustrar dois pontos-chave para entender como o código do R funciona:

  1. Podemos usar objetos para indexar outros objetos.


  1. 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:
  1. a função c() agrupou os números 3 a 5 e 9 (ou seja, c (3:5, 9)):
c(3:5, 9)
[1] 3 4 5 9
  1. R usou esta sequência de números para indexar o vetor nomes_v1
nomes_v1[c(3:5, 9)]
[1] "c" "d" "e" "i"


  1. posteriormente, R usou o vetor ['c', 'd', 'e', 'i'] para indexar v1:
v1[nomes_v1[c(3:5, 9)]]
c d e i 
2 8 6 5 

Indexação por condição


É 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: igual
  • X > Y: maior que
  • X < Y: menor que
  • X >= Y: maior ou igual
  • X <= Y: menor ou igual
  • X | Y: X ou Y
  • X & 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:


v1 > 5
    a     b     c     d     e     f     g     h     i     j 
FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE 


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:

b_v1 <- v1 > 5
v1[b_v1]
 b  d  e  f  h 
10  8  6  9  7 

o

v1[v1 > 5]
 b  d  e  f  h 
10  8  6  9  7 

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

v1[!(v1 <= 10 & v1 > 4 | v1 >= 3)]
c g 
2 1 

Isso é o que aconteceu

v1
 a  b  c  d  e  f  g  h  i  j 
 3 10  2  8  6  9  1  7  5  4 
v1 <= 10 & v1 > 4 | v1 >= 3
    a     b     c     d     e     f     g     h     i     j 
 TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE 
!(v1 <= 10 & v1 > 4 | v1 >= 3)
    a     b     c     d     e     f     g     h     i     j 
FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE 
v1[c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE)]
c g 
2 1 

Algumas funções para explorar atributos dos vetores

length(v1)
[1] 10
class(v1)
[1] "integer"
names(v1)
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
str(v1)
 Named int [1:10] 3 10 2 8 6 9 1 7 5 4
 - attr(*, "names")= chr [1:10] "a" "b" "c" "d" ...

resumindo

  • Vetores: objetos com uma única dimensão.
  • Tipos de vetores: character, logical, numeric y factor.
  • Atributos do vetor: comprimento, tipo e nome.

Tipos do indexação:

  • Posição (e.g. vetor[1], vetor[[1]])
  • Nome (e.g. vetor['nome'], vetor[['nome']])
  • Condição (e.g. vetor[vetor condição valor])

Matrizes

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:

set.seed(123)
v2 <- rpois(6*5, 10)
m <- matrix(data = v2, # dados a incluir en la matriz
            ncol = 5, # número de colunas
            nrow = 6, # número de linhas
            byrow = F) # como os elementos em v2 serão organizados na matriz

Vamos explorar o vetor v2 e ver como ele foi organizado em formato matriz

vetor:

v2
 [1]  8  9 14 10 10 15 11  5  4 13 11 11 10  8 15 11  3  7  6  8  6  8  4  6  6
[26]  8  5 12 12 12

matriz:

m
     [,1] [,2] [,3] [,4] [,5]
[1,]    8   11   10    6    6
[2,]    9    5    8    8    8
[3,]   14    4   15    6    5
[4,]   10   13   11    8   12
[5,]   10   11    3    4   12
[6,]   15   11    7    6   12

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.

rownames(m) <- paste('F', 1:nrow(m), sep = '')
colnames(m) <- paste('C', 1:ncol(m), sep = '')
m
   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

Indexação por posição:

m # matriz inicial
   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
m[1:4, ] # indexando as linhas
   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
m[3:nrow(m), c(1:3, 5)] # indexando linhas e colunas
   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:

m # matriz inicial
   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 colunas
F1 F2 F3 F6 
 6  8  5 12 


Você entende esse código?

Indexação por condição:

m[m[, 1] > 10, 3:5]
   C3 C4 C5
F3 15  6  5
F6  7  6 12

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:

m[1, ]
C1 C2 C3 C4 C5 
 8 11 10  6  6 
is.vector(m[1, ])
[1] TRUE

Para evitar essa redução na dimensionalidade da matriz, usamos o argumento drop = FALSE entre colchetes da indexação.

m[1, , drop = FALSE] # matriz de 1 x 5
   C1 C2 C3 C4 C5
F1  8 11 10  6  6

Algumas funções para explorar atributos da matriz

ncol(m)
[1] 5
nrow(m)
[1] 6
dimnames(m)
[[1]]
[1] "F1" "F2" "F3" "F4" "F5" "F6"

[[2]]
[1] "C1" "C2" "C3" "C4" "C5"
length(m)
[1] 30
str(m)
 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" ...

resumindo

  • Matrizes: son objetos de dos dimensiones, filas y columnas.
  • Elas só podem conter um único tipo de dado: character, logical, numeric y factor.
  • Atributos da matriz: N colunas, N linhas, nomes e tipo.

Indexação:

matriz[linhas, colunas]

\(\rightarrow\)

Array

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().

set.seed(5)
v3 <- rnbinom(6*5*2*2*3, mu = 20, size = 3) 
array1 <- 
  array(data = v3, 
        dim = c(6, 5, 2, 2, 3), 
        dimnames = 
          list(
            paste('F', 1:6, sep = ''), 
            paste('C', 1:5, sep = ''), 
            c('ani_1a', 'ani_1b'),
            c('ani_2a', 'ani_2b'), 
            c('ani_3a', 'ani_3b', 'ani_3c')))
str(array1)
 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"


dim(array1)
[1] 6 5 2 2 3


length(array1)
[1] 360

Indexação por posição:

array1[, , 1, 1, 1]
   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
array1[4:5, 2:3, 1, 2, 2:3]
, , ani_3b

   C2 C3
F4 27 16
F5 10 29

, , ani_3c

   C2 C3
F4 21 53
F5 22  8

Indexação por nome:

array1[, , 'ani_1a', , ]
, , 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.

resumindo

  • Arrays: son mátrices con multidimensionales
  • Elas só podem conter um único tipo de dado: character, logical, numeric y factor.
  • Atributos do vetor: comprimento, colunas, linhas, dimensões, nomes e tipo.

Indexação:

array[linhas, colunas, dimensão 1, ... , dimensão N]

Data frames and Tibbles

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:

tibble(
  var1 = vetor,
  var2 = vetor,
  ...
  var_n = vetor
)

data frames:

data.frame(
  var1 = vetor,
  var2 = vetor,
  ...
  var_n = vetor
)

data frame:

set.seed(123)
df <- 
  data.frame(
    site = rep(c('bosque1', 'bosque2', 'bosque3'), 
            each = 10),
    trap = rep(c(1, 2, 3, 4, 5), each = 2, length.out = 30), 
    formigas = rnbinom(30, mu = 10, size = 3)
  )

tibble:

library(tibble)

set.seed(123)
tib <- 
  tibble(
    site = rep(c('bosque1', 'bosque2', 'bosque3'), 
            each = 10),
    trap = rep(c(1, 2, 3, 4, 5), each = 2, length.out = 30), 
    formigas = rnbinom(30, mu = 10, size = 3)
  )

diferenças do output no console:

data frame:

df
      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:

tib
# 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

Indexação

Vejamos seis maneiras de indexar a mesma coluna do objeto tib:

tib[, 1] # o mesmo que matrizes
# A tibble: 30 × 1
   site   
   <chr>  
 1 bosque1
 2 bosque1
 3 bosque1
 4 bosque1
 5 bosque1
 6 bosque1
 7 bosque1
 8 bosque1
 9 bosque1
10 bosque1
# … with 20 more rows
tib[, 'site'] # o mesmo que matrizes
# A tibble: 30 × 1
   site   
   <chr>  
 1 bosque1
 2 bosque1
 3 bosque1
 4 bosque1
 5 bosque1
 6 bosque1
 7 bosque1
 8 bosque1
 9 bosque1
10 bosque1
# … with 20 more rows
tib[['site']] # diferente de matrizes
 [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).

tib[[1]] # diferente de matrizes
 [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]])

tib[, 1][[1]] # diferente de matrizes
 [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.

resumindo

  • Data frames / tibbles: tabelas de dados relacionais
  • Colunas de qualquer tipo, mas devem ter o mesmo comprimento.
  • Atributos do vetor: N colunas, N linhas, N dimensões, nomes e tipo (colunas).

Indexação:

  • data frame[linhas, colunas]

  • tibble[linhas, colunas]

Listas

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 $:


l1 <- list()


l1$vector <- v1
l1$matriz <- m
l1$array <- array1
l1$tibble <- tib

vamos dar uma olhada na estrutura de l1 \(\rightarrow\)

str(l1)
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:

names(l1)
[1] "vector" "matriz" "array"  "tibble"

As listas são uma estrutura de dados com uma única dimensão:

length(l1)
[1] 4

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):

l1['vector']
$vector
 a  b  c  d  e  f  g  h  i  j 
 3 10  2  8  6  9  1  7  5  4 
l1[names(l1)[c(1:2, 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:


class(l1[2])
[1] "list"
class(l1[[2]])
[1] "matrix" "array" 


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.

  1. Indexamos o objeto de lista (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

l1[['vector']]
 a  b  c  d  e  f  g  h  i  j 
 3 10  2  8  6  9  1  7  5  4 

Passo 2

l1[['vector']][c(1, 3:5)]
a c d e 
3 2 8 6 

Indexando o elemento na quarta posição (tibble)

l1[['tibble']][1, 2:3, drop = F]
# A tibble: 1 × 2
   trap formigas
  <dbl>    <dbl>
1     1        9

As listas podem armazenar outras listas. Pra indexar só temos que prestar atenção na sequência do aninhamento, vejamos um exemplo:

l1$sub_lista <- l1

l1[['sub_lista']][['array']][c(1, 4:4), 3:5, 1, 2, 3]
   C3 C4 C5
F1 16 17  5
F4 53 13 15

Resumindo

  • Listas: podem armazenar qualquer objeto: vetores, matrizes, arrays, data frames, listas, figuras…
  • Não tem restrições.
  • Atributos das listas: comprimento..

Indexação:

  • lista[objeto]

  • lista[[objeto]][indexação do objeto]

  • lista$nome_objeto[indexação do objeto]

“Fim”