Primeiros Passos com o R

Lineu Alberto

Parte 2 - Estruturas, seleção e indexação


1 Estruturas

No R podemos gerar estruturas como:

  1. Vetores (unidimensional, linha ou coluna).
  2. Matrizes (bidimensional, linha e coluna).
  3. Data Frames (vetores concatenados).
  4. Listas (cada elemento pode ser uma estrutura).

Para indexar e selecionar elementos pertencentes às diferentes estruturas existem operadores como:

  • [ ]: é um seletor que retorna um objeto da mesma classe que o objeto original.

  • [[ ]] é usado para extrair elementos de uma lista ou data frame.

  • $ é usado para extrair elementos nomeados de uma lista ou data frame.


Vamos discutir as principais características das estruturas mencionadas:


2 Vetores

Vetores são estruturas de dados básicas do R, que permitem armazenar um conjunto de valores numéricos, caracteres ou lógicos num único objeto. Podemos criar vetores através da função c():

## [1] "numeric"
## [1] "character"
## [1] "logical"

Outra forma de obter vetores lógicos é através de uma expressão condicional em que utiliza-se um operador lógico. Os operadores lógicos utilizados no R são:

Operador Operação
> Maior que
< Menor que
>= Maior ou igual que
<= Menor ou igual que
== Igual
!= Diferente

Além dos operadores lógicos temos os operadores relacionais: &, | e ! (e, ou e não).

Podemos testar, por exemplo, se cada um dos elementos de um dado vetor é exatamente igual a um valor, bem como qualquer outra das operações disponíveis e ainda combiná-las fazendo uso dos operadores & e |. Considere o vetor:

  • Verificando quais dos elementos são iguais a 0.
##  [1] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE
  • Verificando quais dos elementos são maiores que 1.
##  [1]  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE
  • Verificando quais dos elementos são diferentes de 2.
##  [1]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
  • Verificando quais dos elementos estão entre 0 e 3.
##  [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
  • Verificando quais dos elementos são maiores ou iguais a 0 OU menores ou iguais a 3.
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

Caso estejamos interessados em saber quantos dos elementos atendem a condição de interesse, basta somar o vetor lógico resultante com a função sum() que soma elementos de um vetor. Internamente o R interpreta resultados TRUE como 1 e FALSE como 0. Então, no caso que verificamos quais dos elementosestão entre 0 e 3, podemos verificar quantos elementos atendem a condição da seguinte forma:

## [1] 9

Através da função length() verificamos quantos elementos há no vetor, e podemos obter dessa forma a proporção de elementos que atendem a condição:

## [1] 10
## [1] 0.9

Um tipo especial de vetor é chamado fator, trata-se de um vetor de caracteres no qual os elementos são tratados como níveis:

## [1] "factor"
## [1] alto  medio baixo medio alto  alto  baixo
## Levels: alto baixo medio

A ordenação dos níveis pode ser alterada através do argumento levels:

## [1] "factor"
## [1] alto  medio baixo medio alto  alto  baixo
## Levels: alto medio baixo

Os elementos pertencentes ao vetor definem sua classe e lembre-se: todos os elementos do vetor devem ser de mesma classe. Caso isso não seja verdade o R forçará os elementos a mudarem de classe, veja:

## [1] "character"

Mesmo possuindo um elemento de cada tipo o R forçou com que todo o vetor passasse a ser da classe character.


2.1 Sequências

Eventualmente, pode ser necessário gerar números aleatórios ou sequências numéricas e armazenar os valores em um vetor. Vejamos algumas funções com estes objetivos (lembre-se de ler a documentação e verificar os argumentos):

2.1.1 seq()

A função seq() é utilizada para gerar sequências:

##  [1]  1  2  3  4  5  6  7  8  9 10
## [1] 1 3 5 7 9
## [1]  1.00  3.25  5.50  7.75 10.00

2.1.2 rep()

A função rep é utilizada para repetir números:

##  [1] 1 1 1 1 1 1 1 1 1 1
##  [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
##  [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3

2.1.3 runif

A função runif() gera números de uma distribuição uniforme, isto é, gera \(n\) números aleatórios entre um limite inferior e um limite superior, em que todos os valores tem a mesma probabilidade de serem sorteados:

##  [1] 0.44277246 0.86537281 0.67958720 0.15701933 0.16960730 0.51418147
##  [7] 0.62363342 0.07312191 0.92174583 0.34580121
##  [1] 14.22720 14.29567 13.53335 14.02630 14.15890 10.92889 13.13355
##  [8] 13.91124 14.41972 14.30226

2.2 Operações matemáticas em vetores

Operações podem ser feitas entre um vetor e um número, como por exemplo multiplicar todos os elementos de um vetor por uma quantidade. Também é possível realizar operações entre vetores de mesmo comprimento.

##  [1]  6  4  2  9 10  6  3  3  2  3
##  [1]  7  5  3 10 11  7  4  4  3  4
##  [1] 12  8  4 18 20 12  6  6  4  6
##  [1] 12  8  4 18 20 12  6  6  4  6
##  [1]  36  16   4  81 100  36   9   9   4   9

Além disso podemos obter algumas medidas relacionadas a um vetor, tais como comprimento, média, desvio padrão, variância, soma dos elementos, etc. Estas medidas serão vistas com mais detalhes no material em que será apresentada uma análise exploratória completa.

## [1] 10
## [1] 4.8
## [1] 8.177778
## [1] 2.859681
## [1] 48
## [1]  2 10
## [1]  2.0  3.0  3.5  6.0 10.0

2.3 Indexação para Vetores

O principal operador para seleção em vetores são os colchetes. Vejamos alguns exemplos:

  • Criando um vetor numérico:
  • Selecionando o elemento de posição 5:
## [1] 90
  • Selecionando os elementos da posição 1, 2, 3, 4 e 6:
## [1]  1 23  3 47  6
  • Selecionando os primeiros 3 elementos:
## [1]  1 23  3
  • Selecionando todos os elementos exceto o da terceira posição:
##  [1]  1 23 47 90  6  7  8  5  6 10 45
  • Selecionando todos os elementos exceto o primeiro e o quarto:
##  [1] 23  3 90  6  7  8  5  6 10 45

2.4 Seleção Condicional para Vetores

O uso da seleção condicional é feito quando necessitamos obter elementos do vetor que atendem determinada condição. Na prática, podemos estar interessados em um vetor resultado composto de TRUE ou FALSE ou dos elementos que atendem a dondição de interesse. Vejamos de que forma podemos obter tais resultados:

  • Criando um novo vetor numérico:
  • Selecionando os elementos do vetor maiores que 15:
## [1]  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE
## [1] 18 31 56
  • Selecionando os elementos do vetor entre 30 e 100:
## [1] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
## [1] 31 56
  • Selecionando os elementos do vetor que são maiores que 30 ou menores que 100:
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [1] 18 12 31 56  7  5  9

3 Matrizes

Matrizes são estruturas que, assim como os vetores, são capazes de armazenar apenas um tipo de informação. Isto é, todos os elementos da matriz devem ser de alguma das classes básicas: numeric, integer, character, complex ou logical. Contudo as matrizes são estruturas bidimensionais, isso significa que possuem linha e coluna. No R, para criação de uma matriz utiliza-se a função matrix() na qual o usuário informa os elementos sequencialmente por coluna.

## [1] "matrix"
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

Para alterar o preenchimento de forma que seja feito por linha basta utilizar o argumento lógico byrow. Reforçando: sempre leia a documentação da função.

##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9

A função dim() tem duas finalidades: a primeira delas é verificar a dimensão da estrutura, isto é, o número de linhas e o número de colunas. A segunda é gerar uma matriz através de um vetor. Outra forma de verificar número de linhas e colunas é através das funções ncol() e nrow().

  • Gerando um vetor:
## [1] 1 2 3 4 5 6 7 8 9
  • Verificando a dimensão:
## NULL
  • Atribuindo uma nova dimensão:
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
  • Verificando a dimensão:
## [1] 3 3
  • Verificando o número de colunas:
## [1] 3
  • Verificando o número de linhas:
## [1] 3

Para acrescentar linhas e colunas a uma matriz existente basta utilizar as funções rbind() e cbind() para linha e coluna respectivamente.

  • Criando uma matriz:
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
  • Adicionando uma nova linha:
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## [3,]   10   10
  • Adicionando uma nova coluna:
##      [,1] [,2] [,3]
## [1,]    1    3   20
## [2,]    2    4   20

Outras funções importantes para quando trabalhamos com matrizes estão relacionadas à transposição, inversão e criação de matrizes diagonais.

  • Para obter a transposta de uma matriz, basta uitlizar a função t():
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
  • A inversa pode ser obtida através da função solve():
##      [,1] [,2]
## [1,]   -2  1.5
## [2,]    1 -0.5
  • Uma matriz diagonal pode ser criada com a função diag():
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    4    0
## [3,]    0    0    6

Todas as operações matemáticas que fazem uso de matrizes podem ser feitas no R, contudo com cautela, principalmente quando trabalhamos com multiplicação de matrizes.

Vamos considerar duas matrizes:

##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
##      [,1] [,2] [,3]
## [1,]    1    1    1
## [2,]    2    2    2
## [3,]    3    3    3

E vejamos como funcionam as operações adição, subtração, multiplicação por escalar, divisão, multiplicação elemento a elemento e multiplicação matricial.

  • Adição:
##      [,1] [,2] [,3]
## [1,]    2    5    8
## [2,]    3    6    9
## [3,]    4    7   10
  • Subtração:
##      [,1] [,2] [,3]
## [1,]   -1   -1   -1
## [2,]    0    0    0
## [3,]    1    1    1
  • Multiplicação:
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18
  • Divisão:
##      [,1] [,2] [,3]
## [1,]  0.5  2.0  3.5
## [2,]  1.0  2.5  4.0
## [3,]  1.5  3.0  4.5
  • Multiplicação elemento a elemento:
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    4   10   16
## [3,]    9   18   27
  • Multiplicação matricial:
##      [,1] [,2] [,3]
## [1,]   30   30   30
## [2,]   36   36   36
## [3,]   42   42   42

3.1 Indexação e seleção condicional para Matrizes

A indexação funciona de forma muito parecida com o que foi apresentado para vetores, contudo precisamos especificar agora a linha e a coluna para selecionar elementos pertencentes à matriz. Considerando uma das matrizes anteriormente utilizadas:

##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
  • Selecionando o elemento na primeira linha e segunda coluna:
## [1] 4
  • Selecionando todos os elementos da primeira linha:
## [1] 1 4 7
  • Selecionando todos os elementos da segunda coluna:
## [1] 4 5 6
  • Selecionando todos os elementos da segunda coluna porém forçando o output ser uma matriz:
##      [,1]
## [1,]    4
## [2,]    5
## [3,]    6

E alguns exemplos para seleção condicional em matrizes são:

  • Selecionando elementos que são iguais a 1:
##       [,1]  [,2]  [,3]
## [1,]  TRUE FALSE FALSE
## [2,] FALSE FALSE FALSE
## [3,] FALSE FALSE FALSE
## [1] 1
  • Selecionando elementos maiores que 4:
##       [,1]  [,2] [,3]
## [1,] FALSE FALSE TRUE
## [2,] FALSE  TRUE TRUE
## [3,] FALSE  TRUE TRUE
## [1] 5 6 7 8 9
  • Selecionando elementos entre 4 e 5:
##       [,1]  [,2]  [,3]
## [1,] FALSE  TRUE FALSE
## [2,] FALSE  TRUE FALSE
## [3,] FALSE FALSE FALSE
## [1] 4 5
  • Selecionando elementos iguais a 1 ou 5:
##       [,1]  [,2]  [,3]
## [1,]  TRUE FALSE FALSE
## [2,] FALSE  TRUE FALSE
## [3,] FALSE FALSE FALSE
## [1] 1 5

4 Data Frames

Um data frame é composto por diversos vetores de mesmo tamanho que são postos lado a lado numa mesma estrutura. Algo interessante é que não necessariamente estes vetores precisam ser do mesmo tipo.

É o formato mais utilizado para se trabalhar com dados pois comporta a maior parte das situações. Por exemplo, imagine que cada linha representa um indivíduo e cada coluna uma característica de interesse como peso, altura, sexo, etc. Com o data frame é possível organizar a informação de diversos indivíduos e características numa mesma estrutura.

Para criar um data frame no R utilizamos a função data.frame() e todas as funções para descrição da estrutura funcionam.

##   id  nome altura peso sexo
## 1  1 Pedro   1.80   85    M
## 2  2 Maria   1.74   70    F
## 3  3 Paulo   1.90   97    M
## 4  4   Ana   1.65   72    F
## [1] "id"     "nome"   "altura" "peso"   "sexo"
## [1] "data.frame"
## [1] 4 5
## [1] 5
## 'data.frame':    4 obs. of  5 variables:
##  $ id    : num  1 2 3 4
##  $ nome  : Factor w/ 4 levels "Ana","Maria",..: 4 2 3 1
##  $ altura: num  1.8 1.74 1.9 1.65
##  $ peso  : num  85 70 97 72
##  $ sexo  : Factor w/ 2 levels "F","M": 2 1 2 1
## [1] 4
## [1] 5

Tal como para matrizes, as funções cbind() e rbind() funcionam, contudo é possível acrescentar linhas e colunas de outras maneiras.

##   id  nome altura peso sexo coluna
## 1  1 Pedro   1.80   85    M      0
## 2  2 Maria   1.74   70    F      0
## 3  3 Paulo   1.90   97    M      0
## 4  4   Ana   1.65   72    F      0
##   id  nome altura peso sexo
## 1  1 Pedro   1.80   85    M
## 2  2 Maria   1.74   70    F
## 3  3 Paulo   1.90   97    M
## 4  4   Ana   1.65   72    F
## 5  0  nome   0.00    0    x

No caso de acrescentar uma nova coluna a um data frame é possível utilizar o operador $.

##   id  nome altura peso sexo coluna_nova
## 1  1 Pedro   1.80   85    M           0
## 2  2 Maria   1.74   70    F           0
## 3  3 Paulo   1.90   97    M           0
## 4  4   Ana   1.65   72    F           0

4.1 Indexação e seleção condicional para data frames

Para indexação ainda é possível utilizar os colchetes, tal como o que foi visto para vetores e matrizes. O operador $ também é válido para selecionar uma coluna inteira.

  • Selecionando o elemento na primeira linha e quarta coluna:
## [1] 85
  • Selecionando toda a terceira linha:
##   id  nome altura peso sexo coluna_nova
## 3  3 Paulo    1.9   97    M           0
  • Selecionando toda a segunda coluna:
## [1] Pedro Maria Paulo Ana  
## Levels: Ana Maria Paulo Pedro
  • Selecionando a coluna nome através do operador $:
## [1] Pedro Maria Paulo Ana  
## Levels: Ana Maria Paulo Pedro

A seleção condicional pode ser feita de duas formas: uma que segue o mesmo raciocínio do que foi apresentado para as demais estruturas e outra que utiliza a função subset(). Se corretamente utilizadas, ambas retornam o mesmo resultado.

  • Selecionando todas as linhas do data frame em que a variável peso está entre 60 e 80:
##   id  nome altura peso sexo coluna_nova
## 2  2 Maria   1.74   70    F           0
## 4  4   Ana   1.65   72    F           0
##   id  nome altura peso sexo coluna_nova
## 2  2 Maria   1.74   70    F           0
## 4  4   Ana   1.65   72    F           0

5 Listas

Uma lista pode ser interpretada como um caso especial de vetor, em que cada elemento pode ser uma diferente estrutura. Ou seja, em cada posição da lista podemos armazenar vetores, matrizes, data frames e até mesmo outras listas. Criamos listas através da função list().

## $vetor
##  [1] 0.27979550 0.68880731 0.06201166 0.17210869 0.11291905 0.91536054
##  [7] 0.84500293 0.61228082 0.09481930 0.14068507
## 
## $matriz
##           [,1]       [,2]      [,3]
## [1,] 0.2942782 0.88786446 0.1468437
## [2,] 0.4749152 0.02456385 0.9334984
## [3,] 0.5277088 0.48953694 0.3636645
## 
## $df
##             x          y
## 1  0.81135759 0.65612025
## 2  0.09803007 0.58897782
## 3  0.33648236 0.35317954
## 4  0.62803376 0.07791821
## 5  0.16026588 0.75177904
## 6  0.07723845 0.10186752
## 7  0.35278623 0.21917192
## 8  0.26772165 0.44210850
## 9  0.77872338 0.58560339
## 10 0.03944016 0.43510060
## [1] "list"
## [1] "vetor"  "matriz" "df"
## [1] 3
## List of 3
##  $ vetor : num [1:10] 0.28 0.689 0.062 0.172 0.113 ...
##  $ matriz: num [1:3, 1:3] 0.2943 0.4749 0.5277 0.8879 0.0246 ...
##  $ df    :'data.frame':  10 obs. of  2 variables:
##   ..$ x: num [1:10] 0.811 0.098 0.336 0.628 0.16 ...
##   ..$ y: num [1:10] 0.6561 0.589 0.3532 0.0779 0.7518 ...

5.1 Indexação e seleção condicional para listas

A indexação pode ser feita com os colchetes ou com o $, o que muda nas duas abordagens é a estrutura do output. Utilizando os colchetes o resultado será uma lista, enquanto que com o $ a estrutura será a mesma do elemento selecionado na lista. Uma outra forma que resulta no mesmo output do operador $ é através do duplo colchete [[]].

  • Utilizando o operador colchete para acessar o primeiro elemento da lista:
## [1] "list"
## $vetor
##  [1] 0.27979550 0.68880731 0.06201166 0.17210869 0.11291905 0.91536054
##  [7] 0.84500293 0.61228082 0.09481930 0.14068507
  • Utilizando o operador $ para acessar o primeiro elemento da lista:
## [1] "numeric"
##  [1] 0.27979550 0.68880731 0.06201166 0.17210869 0.11291905 0.91536054
##  [7] 0.84500293 0.61228082 0.09481930 0.14068507
  • Utilizando o operador duplo colchete para acessar o primeiro elemento da lista:
## [1] "numeric"
##  [1] 0.27979550 0.68880731 0.06201166 0.17210869 0.11291905 0.91536054
##  [7] 0.84500293 0.61228082 0.09481930 0.14068507

É possível ainda combinar os mecanismos de seleção vistos para acessar elementos de dentro da lista.

  • Acessando os 3 primeiros elementos do vetor armazenado na lista:
## [1] 0.27979550 0.68880731 0.06201166
  • Acessando a segunda linha da matriz armazenada na lista:
## [1] 0.47491519 0.02456385 0.93349842
  • Acessando a coluna nomeada como y do data frame armazenado na lista:
##  [1] 0.65612025 0.58897782 0.35317954 0.07791821 0.75177904 0.10186752
##  [7] 0.21917192 0.44210850 0.58560339 0.43510060

O mesmo raciocínio é válido para seleção condicional.

  • Selecionando elementos armazenados no vetor dentro da lista que estão entre 0,3 e 0,5:
## numeric(0)
  • Selecionando elementos armazenados na matriz dentro da lista que estão entre 0,3 e 0,5:
## [1] 0.4749152 0.4895369 0.3636645
  • Selecionando elementos armazenados no data frame dentro da lista em que a variável nomeada como x apresenta valor maior que 0,6:
##           x          y
## 1 0.8113576 0.65612025
## 4 0.6280338 0.07791821
## 9 0.7787234 0.58560339

6 Coerção

Em algumas situações podemos estar interessados em converter estruturas, ou seja, transformar uma estrutura em outra. A esta tarefa dá-se o nome de coerção. No R existem dois grupos de funções: as do tipo is. e as do tipo as.. As do primeiro tipo verificam se um objeto é de uma determinada classe, enquanto as do segundo são responsáveis pela conversão para uma nova classe.

Considerando os exemplos:

  • Verificando o tipo das estruturas:
## [1] TRUE
## [1] TRUE
## [1] TRUE
## [1] FALSE
## [1] FALSE
## [1] FALSE
  • Efetuando a coerção:
##             [,1]
##  [1,] 0.91889926
##  [2,] 0.13961401
##  [3,] 0.50599602
##  [4,] 0.20003549
##  [5,] 0.11221054
##  [6,] 0.21848078
##  [7,] 0.01783528
##  [8,] 0.09407082
##  [9,] 0.43920156
## [10,] 0.97206441
##         vetor
## 1  0.91889926
## 2  0.13961401
## 3  0.50599602
## 4  0.20003549
## 5  0.11221054
## 6  0.21848078
## 7  0.01783528
## 8  0.09407082
## 9  0.43920156
## 10 0.97206441
##          V1        V2         V3
## 1 0.7379016 0.1003507 0.35812702
## 2 0.7274921 0.5124829 0.74684495
## 3 0.5637241 0.9224633 0.05369693
## [1] 0.73790162 0.72749214 0.56372408 0.10035073 0.51248287 0.92246330
## [7] 0.35812702 0.74684495 0.05369693
##                x          y
##  [1,] 0.44795601 0.57224154
##  [2,] 0.11089801 0.50524654
##  [3,] 0.34964420 0.08145900
##  [4,] 0.69083108 0.87221093
##  [5,] 0.14376272 0.07318994
##  [6,] 0.61976771 0.18520698
##  [7,] 0.83918824 0.69227319
##  [8,] 0.06187371 0.25415830
##  [9,] 0.75435727 0.43582136
## [10,] 0.07261673 0.55226260

7 Valores perdidos

Valores perdidos, também chamados de missing, são informações que por algum motivo não puderam ser obtidas. Fique atento, um valor perdido não é 0. Valores perdidos são definidos como NA (not available).

## [1]  1 NA  3  7 NA

A presença de valores perdidos não altera a classe do objeto:

## [1] "numeric"

E podemos verificar se existe algum NA no objeto através da função is.na.

## [1] FALSE  TRUE FALSE FALSE  TRUE

Caso seja necessário excluir os valores ausentes pode-se usar a função na.omit(x).

## [1] 1 3 7
## attr(,"na.action")
## [1] 2 5
## attr(,"class")
## [1] "omit"

Outros valores especiais similares ao NA são o NaN (not a number), Inf e -Inf (mais ou menos infinito).

## [1] NaN
## [1] Inf
## [1] -Inf

Recomendo fortemente a leitura dos seguintes materiais, os quais usei como base para produção desse texto:


Críticas e sugestões a este material sempre serão bem vindas.

Para entrar em contato comigo, envie uma mensagem para .