Capítulo 3 Trabalhando com arrays

Bom, depois dessa pequena pausa vamos continuar conhecendo outros tipos de objetos no R. Até agora já trabalhamos com objetos bem simples que armazenam apenas uma informação por vez mas, na maioria das vezes, precisamos conseguir armazenar em uma mesma variável muitas informações ao mesmo tempo. Esses objetos maiores s~ao conhecidos como arrays.

3.1 Vetores

Um tipo de objeto um pouco mais complexo é o do tipo vetor. A sintaxe para a criação de um vetor é c(), onde os itens internos do vetor são separados por virgula. Assim, se criamos um vetor c(2, 3, 4, 5), criamos um vetor de tamanho 4 que armazena os itens 2, 3, 4 e 5. O vetor seria o equivalente a uma linha de uma tabela.

A partir de agora passaremos a tratar de tamanhos de objetos. O vetor nada mais é que uma matriz de tamanho 1 x c, ou seja, 1 linha e c colunas.

A principal característica do vetor é que ele só armazena objetos do mesmo tipo, ou seja, só podemos ter vetores só de interger ou só de numeric ou só de character ou só de logical. Dessa forma, o vetor irá herdar a classe dos objetos que ele contêm. Sendo assim, para termos vetores da classe numeric precisamos criar um vetor com objetos da classe numeric dentro dele.

Exercício 3.1 Crie um vetor de classe numeric, logical e character e atribua cada um deles a uma variável diferente.

 

Exercício 3.2 Pergunte ao R a classe de cada um dos vetores.

 

Bom, como o vetor herda as características da classe então podemos fazer operações matemáticas com os vetores numéricos.

Exercício 3.3 Multiplique o seu vetor numeric por um número.

  O que aconteceu? Ele mudou o seu vetor original?

 
Exercício 3.4 Agora crie mais um vetor numeric (do mesmo tamanho) e multiple os dois vetores.

O que o R fez?

E se tivéssemos vetores de tamanho diferente?

 
Exercício 3.5 Multiplique dois vetores numeric de tamanhos diferentes.

 

O que aconteceu?

O R, diferente de outras linguagens, quando solicitado que faça operações com vetores de tamanhos diferentes ele faz uma reciclagem: alinha os dois vetores e, caso não possuam o mesmo tamanho, vai repetindo o vetor menor até completar o vetor maior. Outras linguagens não permitiriam a operação e retornariam um erro.

A letra c na sintaxe da criação de um vetor vem da palavra combine pois o vetor nada mais é do que a combinação de vários objetos na sequência.

3.1.1 Nomeação de vetores

Podemos vincular nomes aos vetores com a função names(), da seguinte forma:

sacola1 <- c(10, 5, 8, 7)
names(sacola1) <- c("Laranja", "Pera", "Uva", "Maça")

Agora quando pedimos para ver o vetor nomeado ele aparece da seguinte forma:

sacola1
## Laranja    Pera     Uva    Maça 
##      10       5       8       7

No caso, como temos apenas uma sacola de feira, o jeito que fizemos faz sentido: atribuímos um vetor e depois usamos a função names para nomeá-lo. Mas e se tivermos mais de um vetor de sacolas de feira, com as mesmas características dentro?

sacola2 <- c(5, 9, 7, 6)
sacola3 <- c(8, 7, 5, 4)
sacola4 <- c(9, 12, 3, 9)
sacola5 <- c(5, 3, 10, 12)

Agora faz sentido otimizarmos a nossa função. Para isso criamos um vetor chamado nomes e associamos ele a cada uma dos vetores:

nomes <- c("Laranja", "Pera", "Uva", "Maça")
names(sacola2) <- nomes
names(sacola3) <- nomes
names(sacola4) <- nomes
names(sacola5) <- nomes

Pronto! Conseguimos nomear todos os vetores de forma mais rápida.

3.1.2 Operações com vetores

Agora queremos saber qual foi o total de cada fruta comprada. Como já sabemos como fazer operações matemáticas com vetores precisamos apenas somar os vetores correspondentes das nossas sacolas de feira e adicionar em um vetor de soma.

soma_feira <- sacola1 + sacola2 + sacola3 + sacola4 + sacola5
soma_feira
## Laranja    Pera     Uva    Maça 
##      37      36      33      38

Agora o nosso vetor soma_feira armazena a soma de cada fruta em todas as sacolas de feira. Assim, podemos responder: quantas laranjas foram compradas no total? Qual foi a fruta mais comprada?

O vetor total não é nomeado. Podemos nomeá-lo. Usando a função names.

 

Exercício 3.6 Nomeie o vetor total de sacolas de feira.

 

Mas e se quisermos saber a soma de itens de cada sacola? Nesse caso, fazer operaçóes com vetores não nos ajuda. Em outras linguagens de programação teríamos que programar laços de repetição e laços condicionais para realizar essa operação e, se quiséssemos utilizar em outras situações (reaproveitá-la) teríamos que programar uma função. O R por já vir com varias funções pré-programadas facilita o nosso trabalho. Sendo assim, precisamos apenas utilizar a função sum()10 (olhe a documentação da função).

 

Exercício 3.7 Faça a soma de cada um dos vetores de sacolas utilizando a função sum(). Armazene cada resultado em uma nova variável.

 

Exercício 3.8 Descubra o total de itens comprados na feira utilizando a função sum(). Armazene cada resultado em uma nova variável.

 

3.1.3 Selecionar elementos dentro de um vetor

Algo útil para fazermos é conseguirmos selecionar elementos dentro dos vetores. Para isso precisamos entender o conceito de endereçamento. Por exemplo, o vetor de tamanho quatro tem quatro espaços dentro dele, dentro de cada um desses espaços está armazenado um objeto (um número, um texto ou um objeto de tipo lógico), ou seja, esse vetor tem 4 “endereços” dentro dele. Isso nos facilita pois nem sempre sabemos o que tem dentro do vetor e para descobrirmos não precisamos pedir para o R nos retornar o vetor inteiro (às vezes o vetor é muito grande e esse precedimento se torna inviável).

Para indicarmos que queremos ver algo dentro de um endereço utilizamos a sintaxe de []. Para indicarmos um endereço de um vetor utilizamos a sintaxe vetor[x], onde x indica um número de 1 ate n (a maior casa do vetor).

 

Exercício 3.9 Selecione o elemento 4 do vetor da sacola 3. Atribua esse valor a uma variável.

 

Podemos também selecionar mais de um valor do vetor. A sintaxe é indicar dentro dos [] a seleção a ser selecionada. Veja que isso indica um novo vetor então a sintaxe também deve seguir a sintaxe de um vetor: vetor[c(x, y, z)]. Se os números indicam um intervalo podemos utilizar a sintaxe vetor[x:y].

 

Exercício 3.10 Selecione do vetor sacola3 os valores 1 e 3 e do vetor sacola2 os valores de 2 a 4.

 

Para vetores nomeados é possível selecionar a partir dos nomes. A lógica é a mesma, mas dentro dos [] adicionamos o nome entre " " (por ser uma variável de classe textual). Para selecionarmos mais de um nome também fazemos do mesmo jeito.

 

Exercício 3.11 Selecione a quantidade de laranjas do vetor da sacola 4. Selecione a quantidade de peras e maças do vetor da sacola 5.

3.1.4 Comparações de vetores e entre vetores

Assim como fizemos comparações entre os objetos criados, podemos fazer comparações entre os vetores. Compare o vetor sacola1 com o vetor sacola2. Quando utilizamos os operadores relacionais entre dois vetores o R retorna a comparação de cada um dos itens, ou seja, a comparação do item 1 do primeiro vetor com o item 1 do segundo vetor e assim por diante. Retornando TRUE ou FALSE em cada um deles. Em vetores nomeados com os mesmos nomes esse procedimento é ainda mais fácil pois o R nos retorna o resultado das comparações com os nomes dos vetores.

 

Exercício 3.12 Qual dos itens do vetor sacola2 são maiores que os itens do vetor sacola4?

 

Também podemos fazer essas comparações com a soma de cada sacola.

 

Exercício 3.13 A soma dos itens da sacola3 é menor que a soma dos itens da sacola5?

 

Podemos utilizar os mesmos sinais de comparação para saber quais os valores de um vetor são maiores que um número, por exemplo. Assim se perguntarmos ao R vetor > 5 ele irá nos responder elemento por elemento se é ou não maior que cinco (respondendo com operadores lógicos).

 

Exercício 3.14 Veja quais casas do vetor da sacola 5 tem valores maiores ou iguais a 10.

 

Porém, seria mais útil se tivessemos como retorno os números que correspondem a busca que desejamos. Para isso, precisamos inserir vetor[vetor > x]. Aqui o R irá retornar os números que são maiores que x. No caso do vetor nomeado a resposta virá acompanhada dos nomes. Lembre-se que dessa forma não temos como saber quais casas tem os valores retornados, o R retorna os elementos que são TRUE no seu vetor mas não indica qual era a posição original. Esse é o nosso primeiro contato um tipo de filtragem dos dados.

 

Exercício 3.15 Armazene em uma variável os valores do vetor sacola1 que são menores do que 10.

 

3.1.5 Adição e exclusão de valores em um vetor

Podemos adicionar e excluir valores de um vetor existente. Para adicionarmos valores em um vetor podemos fazer de três formas distintas:

  • Por endereçamento direto - dessa forma precisamos indicar dentro dos colchetes o endereço da última casa mais um:
    • vetor[x+1] <- 5
  • Por endereçamento indireto - dessa forma não precisamos saber o tamanho do vetor, indicamos a partir da função length() o tamanho do vetor + 1
    • vetor[length(vetor) + 1] <- 9
  • Por recursividade - substituímos o vetor original por um novo vetor que tem o vetor original seguido de uma casa antes e/ou depois
    • vetor <- c(vetor, 10)
    • vetor <- c(10, vetor)

Das duas primeiras formas, se indicamos um número diferente de 1 no endereço o R, diferente de outras linguagens, coloca NA nas casas entre a última casa do vetor e a casa nova atribuída. Veja o exemplo a seguir.

vetor1 <- c(1, 2, 4)
vetor1[5] <- 5
vetor1
## [1]  1  2  4 NA  5

Como o vetor tinha inicialmente 3 casas e indicamos um valor para uma 5ª casa, o R criou a 5ª casa com o valor indicado, mas precisava para tanto criar uma 4ª casa também. Essa ele incluiu um valor NA pois o valor dessa casa não foi indicado.

 

Exercício 3.16 Adicione os valores de soma, calculados anteiormente, nos respectivos vetores de sacolas de feira.

 

Por fim, para excluir elementos de um vetor, indicamos por recursividade o vetor dentro de [] os valores que queremos excluir com um traço na frente. Se queremos excluir um intervalo indicamos [-c(x:y)] e se queremos excluir números específicos indicamos [-c(x, y, z)].

vetor1 <- vetor1[-c(4)]
vetor1
## [1] 1 2 4 5

No caso da exclusão não é necessario que seja por recursividade. É possivel atribuir um novo vetor para o procedimento.

3.1.6 Funções com vetores

Na última parte dessa aula iremos aprender algumas funções úteis para utilizar em vetores. Ainda que possamos criar vetores de sequência utilizando apenas a sintaxe x:y, por exemplo as funções rep() e seq() nos auxiliam a criar sequências mais personalizadas.

#Criando sequências sem as funções rep() ou seq()
seq1 <- 1:8
seq1
## [1] 1 2 3 4 5 6 7 8
seq2 <- 2.5:10
seq2
## [1] 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5

A função seq() possibilita personalizar outros argumentos para a criação da sequência. O principal argumento é o by em que podemos definir o incremento da sequência. Por exemplo, se quero uma sequência de 0 a 10 de 2 em 2 utilizo: seq(0, 10, by = 2). Veja outros argumentos na documentação da função seq().

 

Exercício 3.17 Crie um vetor com uma sequência de numeros iniciando em -20 e indo ate 50 de 5 em 5. Atribua a uma variável.

 

A função rep() possibilita a criação de sequências de numeros repetidos. Por exemplo, se utilizarmos rep(5,3) iremos ter um vetor com o número 5 repetido 3 vezes.

rep(5,3)
## [1] 5 5 5

Para ter um intervalo podemos utilizar rep(x:y, n), ou seja, um intervalo que vai de x a y repetido n vezes.

rep(1:5, 3)
##  [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

Por fim, podemos criar um intervalo repetindo cada número do intervalo n vezes.

rep(1:5, each = 3)
##  [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5

Outras funções úteis para aprendermos agora são:

  • mean(x) - cálculo da média do vetor x
  • var(x) - cálculo da variância do vetor x
  • max(x) - o valor máximo encontrado no vetor x
  • min(x) - o valor mínimo encontrado no vetor x
  • sd(x) - o desvio padrão do vetor x
  • range(x) - a amplitude do vetor x
  • length(x) - o tamanho do vetor x
  • rev(x) - inverter o vetor x Atenção: isso não altera o vetor original

Se colocarmos duas ou mais classes diferentes dentro de um mesmo vetor, o R vai forçar que todos os elementos passem a pertencer à mesma classe. Ordem de preferência: character > complex > numeric > integer > logical

3.2 Matrizes

Matrizes são vetores (arrays) bidimensionais. Justamente por serem vetores, herdam a mesma característica dos vetores: podem ser apenas de uma mesma classe. Para criar uma matriz precisamos utilizar a função matrix(), mas atenção é necessário tomar cuidado com o argumento byrow. Por padrão a função matrix() define o argumento byrow como FALSE e portanto, preenche a matriz por colunas. Se quisermos que preencher por linhas precisamos atribuir o argumento byrow como TRUE. Veja a diferença:

matrix(1:30, byrow = FALSE, nrow = 10) 
##       [,1] [,2] [,3]
##  [1,]    1   11   21
##  [2,]    2   12   22
##  [3,]    3   13   23
##  [4,]    4   14   24
##  [5,]    5   15   25
##  [6,]    6   16   26
##  [7,]    7   17   27
##  [8,]    8   18   28
##  [9,]    9   19   29
## [10,]   10   20   30

O comando anterior criou uma matriz de 1 a 30 preenchendo por colunas. Agora alterando o argumento byrow:

matrix(1:30, byrow = TRUE, nrow = 10)
##       [,1] [,2] [,3]
##  [1,]    1    2    3
##  [2,]    4    5    6
##  [3,]    7    8    9
##  [4,]   10   11   12
##  [5,]   13   14   15
##  [6,]   16   17   18
##  [7,]   19   20   21
##  [8,]   22   23   24
##  [9,]   25   26   27
## [10,]   28   29   30

Apesar do primeiro e último item das duas matrizes serem os mesmos todos os outros são bem diferentes. O agumento nrow define o número de linhas que desejamos na matriz. No caso, como temos 30 numeros e definimos que queremos 10 linhas teremos 3 colunas (30/10 = 3). Se definíssemos 5 linhas teriamos 6 colunas. Como a seguir:

matrix(1:30, byrow = TRUE, nrow = 5)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    2    3    4    5    6
## [2,]    7    8    9   10   11   12
## [3,]   13   14   15   16   17   18
## [4,]   19   20   21   22   23   24
## [5,]   25   26   27   28   29   30

Utilize sempre múltiplos do número desejado se não o R faz a reciclagem das casas e cria uma matriz maior do que a desejada. Como a seguir:

matrix(1:30, byrow = TRUE, nrow = 7)
## Warning in matrix(1:30, byrow = TRUE, nrow = 7): data length [30] is not a sub-
## multiple or multiple of the number of rows [7]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    2    3    4    5
## [2,]    6    7    8    9   10
## [3,]   11   12   13   14   15
## [4,]   16   17   18   19   20
## [5,]   21   22   23   24   25
## [6,]   26   27   28   29   30
## [7,]    1    2    3    4    5

De modo equivalente o argumento ncol define o número de colunas da matriz. Os dois argumentos são complemetares, não sendo necessário utilizá-los concomitantemente.

Vamos criar uma matriz com os vetores que tínhamos anteriormente (sacolas de feira). Primeiro criamos um vetor com todas as sacolas concatenadas:

sacolas <- c(sacola1, sacola2, sacola3, sacola4, sacola5)
sacolas
## Laranja    Pera     Uva    Maça Laranja    Pera     Uva    Maça Laranja    Pera 
##      10       5       8       7       5       9       7       6       8       7 
##     Uva    Maça Laranja    Pera     Uva    Maça Laranja    Pera     Uva    Maça 
##       5       4       9      12       3       9       5       3      10      12

Cuidado com a ordem das sacolas!

Depois criamos uma matriz com essas sacolas. Cuidado com o argumento byrow! Aqui precisamos que a matriz seja preenchida por linhas, então o argumento byrow deve ser verdadeiro! O argumento nrow será o número das nossas sacolas.

matriz_sacola <- matrix(sacolas, byrow = T, nrow = 5)
matriz_sacola
##      [,1] [,2] [,3] [,4]
## [1,]   10    5    8    7
## [2,]    5    9    7    6
## [3,]    8    7    5    4
## [4,]    9   12    3    9
## [5,]    5    3   10   12

Veja que agora o R criou um objeto diferente: do tipo Data. Isso significa que o R interpreta a matriz de forma diferente dos vetores e objetos simples. Uma outra forma de fazer a matriz é fazer de forma direta o vetor dentro do primeiro argumento: matrix(c(sacola1, sacola2, sacola3, sacola4, sacola5), byrow = T, nrow = 5)

Porém ao transformar em matriz perdemos os nomes dos nossos vetores (nossas colunas). Vamos criá-los novamente.

Para criar os nomes das colunas precisamos utilizar agora a função colnames. Precisamos especificar onde vão os nomes pois agora não estamos mais trabalhando com vetores unidimensionais. Para isso podemos reaproveitar o nosso vetor nomes, que utilizamos anteriormente.

colnames(matriz_sacola) <- nomes

Dissemos para o R que os nomes das colunas de matriz_sacola correspondem ao vetor nomes.

Agora precisamos definir os nomes das nossas linhas. Para isso utilizamos a função rownames. Como não temos nenhum vetor de nomes para linhas vamos fazer direto dentro da função:

rownames(matriz_sacola) <- c("sacola1", "sacola2", "sacola3", "sacola4", "sacola5")

Pronto! Agora temos uma matriz com nomes nas linhas e colunas.

matriz_sacola
##         Laranja Pera Uva Maça
## sacola1      10    5   8    7
## sacola2       5    9   7    6
## sacola3       8    7   5    4
## sacola4       9   12   3    9
## sacola5       5    3  10   12

Agora queremos fazer as somas das linhas e das colunas. Esse processo pode ser um pouco confuso, por isso precisamos tomar bastante cuidado!

Primeiro fazemos as somas das linhas, ou seja, criamos um vetor que tem a soma das linhas. Como temos 5 linhas, esse vetor terá 5 elementos. Para isso utilizamos a função rowSums() na nossa matriz, criando um vetor de soma:

somaL <- rowSums(matriz_sacola)
somaL
## sacola1 sacola2 sacola3 sacola4 sacola5 
##      30      27      24      33      30

Esse vetor será correspondente a uma nova coluna da nossa matriz. Por isso utilizamos a função cbind() para colar essa nova coluna na nossa matriz. A função cbind() precisa como primeiro argumento o nome da nossa matriz e como segundo o que vamos colar nela (o vetor somaL). Porém a função não sobrescreve a matriz original, então precisamos atribuir toda a função a matriz original:

matriz_sacola <- cbind(matriz_sacola, somaL)
matriz_sacola
##         Laranja Pera Uva Maça somaL
## sacola1      10    5   8    7    30
## sacola2       5    9   7    6    27
## sacola3       8    7   5    4    24
## sacola4       9   12   3    9    33
## sacola5       5    3  10   12    30

Agora queremos a soma das colunas. Para isso utilizamos a função colSums() e atribuímos ela a um vetor:

somaC <- colSums(matriz_sacola)
somaC
## Laranja    Pera     Uva    Maça   somaL 
##      37      36      33      38     144

O vetor somaC será correspondente a uma nova linha da nossa matriz. Assim, precisamos unir essa linha a nossa matriz. Para isso, utilizamos a função rbind(). Da mesma forma que a função cbind() funciona, a função rbind() não sobrescreve a matriz original. Portanto, precisamos atribuir essa função à matriz original:

matriz_sacola <- rbind(matriz_sacola, somaC)
matriz_sacola
##         Laranja Pera Uva Maça somaL
## sacola1      10    5   8    7    30
## sacola2       5    9   7    6    27
## sacola3       8    7   5    4    24
## sacola4       9   12   3    9    33
## sacola5       5    3  10   12    30
## somaC        37   36  33   38   144

De modo a diminuir os passos é possível unir o passo 1 e 2 da seguinte forma: cbind(rowSums(matriz_sacola), matriz_sacola). E os passos 3 e 4 da seguinte forma: rbind(colSums(matriz_sacola), matriz_sacola). Sempre atribuindo a matriz_sacola.

3.2.1 Seleção de elementos matriz

Podemos selecionar elementos internos dentro de uma matriz. Para tanto, precisamos indicar o endereço que queremos, como fizemos com a seleção de vetores. Porém dessa vez precisamos indicar o endereço da linha e da coluna. A sintaxe para esse tipo de seleção é: matrix[x, y] onde x é o número da linha que você quer selecionar e y o número da coluna.

 
Exercício 3.18 Selecione o terceiro elemento da segunda coluna da matriz_sacola.

 

Da mesma forma, podemos selecionar uma coluna ou uma linha inteira da matriz. Para selecionar uma linha inteira deixamos o valor de y vazio e se quisermos selecionar uma coluna inteira deixamos o valor de x vazio.

 
Exercício 3.19 Selecione a 5ª linha da matriz_sacola.

 

 
Exercício 3.20 Selecione a 3ª coluna da matriz_sacola.

 

3.2.2 Operações com matrizes

Da mesma forma que fizemos operações com os vetores podemos fazer operações (+, -, /, *, ^, %%, %/%) de matrizes com escalares, com vetores ou com outras matrizes. Apenas temos que tomar cuidado com o tamanho das matrizes. Se elas forem de tamanho diferentes o R irá reciclar (repetir) a matriz menor.

O operador * não é equivalente a multiplicação matricial das matrizes. Utilizando esse operador o R multiplica o primeiro item da matriz A com o primeiro item da matriz B. Para realizar multiplicação matricial precisamos utilizar o operador %*%.

 
Exercício 3.21 Some duas matrizes do mesmo tamanho. Atribua o resultado a uma terceira matriz.

 

 
Exercício 3.22 Some uma matriz com um vetor. Atribua o resultado a uma terceira matriz.

 

3.3 Factors

Factor11 é uma estrutura de dados no R utilizada para armazenar variáveis categóricas. São considerados como uma classe especial de vetores e utilizados, principalmente, em análises estatísticas – as variáveis categóricas são interpretadas por modelos estatísticos de forma diferente das variáveis contínuas. Assim, quando armazenamos dados como factors garantimos que diversas funções presentes nos pacotes do R tratem esses dados de forma correta.

Ao utilizarmos a função factor() o R armazena um vetor de valores inteiros com os correspondentes em rótulos categóricos para serem usados quando o factor é solicitado.

Por exemplo, se tenho um vetor numerico de 0 e 1 e utilizo a função factor() informando ao R que o 0 equivale masculino e 1 equivale a feminino. Ele irá interpretar os 0 e os 1 do meu vetor com o seus respectivos rótulos:

genero <- c(0, 1, 0, 1, 1, 0, 0, 1)
genero <- factor(genero, labels = c("feminino", "masculino"))

Da mesma forma, posso inserir um vetor textual e utilizar a função factor(), o R irá interpretar todos os diferentes caracteres do vetor como um nível diferente. Desse jeito, precisamos tomar cuidado ao inserir os elementos textuais pois “f” é diferente de “F” e o R interpretaria como 2 níveis diferentes.

genero <- c("M", "F", "F", "M", "M", "F", "F", "M")
genero <- factor(genero)

Também podemos fazer factors que sejam ordenados, ou seja, informar que existe uma ordem pré-estabelecida das categorias. Para isso adicionamos o argumento order = T e no argumento levels inserimos as categorias na ordem desejada:

vetor_satisf <- c("Bom", "Ruim", "Excelente", "Razoável", "Razoável", "Ótimo", "Bom", "Péssimo", "Excelente")
vetor_satisf <- factor(vetor_satisf, order = TRUE, levels = c("Péssimo", "Ruim", "Razoável", "Bom", "Ótimo", "Excelente"))

Se informamos que há uma ordem das categorias (order= TRUE), mas não especificamos a ordem no argumento levels o R irá definir a ordem pela ordem alfabética dos fatores.

3.4 Dataframes

Como os elementos dentro de uma matriz não podem ser de classes/tipos diferentes precisamos de um outro tipo de objeto para tratar banco de dados quando queremos trabalhar com vários tipos de dados. Um dataframe é capaz de armazenar objetos de classes diferentes e trata as colunas como variáveis e as linhas como observações (casos). Porém, não podemos armazenar objetos de classes diferentes dentro de uma mesma coluna (ou variável).

Para criar um dataframe utilizamos a função data.frame(). Podemos indicar vetores ou uma matriz para serem transformados em data frames. Porém, a função data.frame() vê os vetores inseridos como colunas. Então, para trnasformar os nossos vetores sacolas em data frame precisamos ou primeiro transformar eles em uma matriz e preenchê-lo da maneira correta ou utilizamos a função transpose() do pacote data.table (dessa forma não teremos os nomes das linhas, das colunas, a soma das linhas ou das colunas).

data_sacola <- data.frame(matriz_sacola)
data_sacola
##         Laranja Pera Uva Maça somaL
## sacola1      10    5   8    7    30
## sacola2       5    9   7    6    27
## sacola3       8    7   5    4    24
## sacola4       9   12   3    9    33
## sacola5       5    3  10   12    30
## somaC        37   36  33   38   144

Criamos um data frame com os dados das sacolas que tínhamos mas o nosso maior objetivo é utilizar data frames para banco de dados com classes de objetos diferentes. Vamos, então, criar um data frame com variáveis de diversos tipos. Dentro de cada linha da função data.frame() há a criação de uma variavel. As que tem a função sample() fazem sorteios dentro dos limites especificados (com repetição), as com a função factor() criam variáveis categóricas com a repetição definida no vetor do segundo argumento e a função paste() cria uma sequência de 0000 seguida de números de 1 a 30 (o equivalente de um ID de indivíduos). Por fim, a função colnames() define os nomes das colunas do nosso banco:

banco <- data.frame(paste("0000", 1:30, sep = ""), 
                    factor(rep(c("b", "n", "i", "o"), c(10, 10, 6, 4))), 
                    factor(rep(c("f","m"), c(16,14))), 
                    sample(c(16:60), 30, replace = T), 
                    factor(rep(c("superior","tecnico", "medio", "fundamental"), c(5, 8, 12, 5))), 
                    sample(seq(1000, 30000, by = 1000), 30, replace = T),  
                    factor(rep(c("solteiro","casado", "viuvo", "separado"), c(10, 10, 2, 8))))  
colnames(banco) <- c("individuo", "raca", "sexo", "idade", "escol", "renda", "civil") 
banco
##    individuo raca sexo idade       escol renda    civil
## 1      00001    b    f    28    superior 10000 solteiro
## 2      00002    b    f    28    superior  2000 solteiro
## 3      00003    b    f    44    superior 28000 solteiro
## 4      00004    b    f    58    superior 19000 solteiro
## 5      00005    b    f    26    superior  7000 solteiro
## 6      00006    b    f    52     tecnico 10000 solteiro
## 7      00007    b    f    20     tecnico  4000 solteiro
## 8      00008    b    f    19     tecnico 18000 solteiro
## 9      00009    b    f    42     tecnico 20000 solteiro
## 10    000010    b    f    32     tecnico 30000 solteiro
## 11    000011    n    f    49     tecnico 19000   casado
## 12    000012    n    f    54     tecnico 10000   casado
## 13    000013    n    f    24     tecnico 11000   casado
## 14    000014    n    f    43       medio  7000   casado
## 15    000015    n    f    19       medio 23000   casado
## 16    000016    n    f    35       medio 12000   casado
## 17    000017    n    m    55       medio 23000   casado
## 18    000018    n    m    23       medio 19000   casado
## 19    000019    n    m    26       medio 26000   casado
## 20    000020    n    m    36       medio 18000   casado
## 21    000021    i    m    18       medio 30000    viuvo
## 22    000022    i    m    32       medio 12000    viuvo
## 23    000023    i    m    40       medio 13000 separado
## 24    000024    i    m    20       medio 28000 separado
## 25    000025    i    m    52       medio 23000 separado
## 26    000026    i    m    46 fundamental 27000 separado
## 27    000027    o    m    54 fundamental 24000 separado
## 28    000028    o    m    43 fundamental 28000 separado
## 29    000029    o    m    21 fundamental 23000 separado
## 30    000030    o    m    41 fundamental 17000 separado

Como as variáveis idade e renda são construídas a partir de um sorteio aleatório cada vez que o código é rodado são criados resultados diferentes.

3.4.1 Funções básicas para data frames

Toda a vez que abrimos um novo data frame é importante utilizarmos 4 funções básicas: head(), tail(), str() e summary().

As funções head() e tail() mostram, respectivamente, os primeiros e os últimos 6 casos (linhas) do seu banco de dados. Se você quiser aumentar o número de linhas mostrado precisa adicionar o argumento n = e definir a quantidade desejada.

 
Exercício 3.23 Mostre os 10 primeiros e 10 últimos itens do data frame banco.

 

A função str() retorna a estrutura de cada uma das variáveis do banco:

str(banco)
## 'data.frame':	30 obs. of  7 variables:
##  $ individuo: Factor w/ 30 levels "00001","000010",..: 1 12 23 25 26 27 28 29 30 2 ...
##  $ raca     : Factor w/ 4 levels "b","i","n","o": 1 1 1 1 1 1 1 1 1 1 ...
##  $ sexo     : Factor w/ 2 levels "f","m": 1 1 1 1 1 1 1 1 1 1 ...
##  $ idade    : int  28 28 44 58 26 52 20 19 42 32 ...
##  $ escol    : Factor w/ 4 levels "fundamental",..: 3 3 3 3 3 4 4 4 4 4 ...
##  $ renda    : num  10000 2000 28000 19000 7000 10000 4000 18000 20000 30000 ...
##  $ civil    : Factor w/ 4 levels "casado","separado",..: 3 3 3 3 3 3 3 3 3 3 ...

E a função summary() retorna um resumo de todas as variáveis:

summary(banco)
##    individuo  raca   sexo       idade              escol        renda      
##  00001  : 1   b:10   f:16   Min.   :18.0   fundamental: 5   Min.   : 2000  
##  000010 : 1   i: 6   m:14   1st Qu.:24.5   medio      :12   1st Qu.:11250  
##  000011 : 1   n:10          Median :35.5   superior   : 5   Median :19000  
##  000012 : 1   o: 4          Mean   :36.0   tecnico    : 8   Mean   :18033  
##  000013 : 1                 3rd Qu.:45.5                    3rd Qu.:23750  
##  000014 : 1                 Max.   :58.0                    Max.   :30000  
##  (Other):24                                                                
##       civil   
##  casado  :10  
##  separado: 8  
##  solteiro:10  
##  viuvo   : 2  
##               
##               
## 

Com essas funções conseguimos ver como o R está interpretando cada uma das variáveis. Já vimos, por exemplo, que ele armazenou a variável indivíduo como um factor, o que não é o que gostaríamos. Depois veremos como transformar essa variável em texto.

3.4.2 Selecionando elementos dentro de um dataframe

Para selecionar elementos dentro de um dataframe podemos trabalhar com a mesma lógica das matrizes. Utilizando os símbolos [ , ] para delimitar a linha (ou intervalo de linhas) e a coluna (ou intervalo de colunas).

 
Exercício 3.24 Selecione o elemento que está armazenado na linha 20 e na coluna 4.

 

 
Exercício 3.25 Selecione a linha 10 inteira. Selecione a coluna 2 inteira.

 

Podemos também selecionar um intervalo dentro de uma coluna. Para isso colocamos o intervalo de linhas que queremos (p.ex. 4:15) e colocamos o número da coluna desejada. Porém, como nomeamos as nossas colunas, podemos colocar o nome da coluna no lugar do número:

banco[9:20, "renda"]
##  [1] 20000 30000 19000 10000 11000  7000 23000 12000 23000 19000 26000 18000

Da mesma forma, podemos selecionar variáveis de um caso ou de uma seleção de casos:

banco[c(3, 4, 8), 3:5]
##   sexo idade    escol
## 3    f    44 superior
## 4    f    58 superior
## 8    f    19  tecnico

No exemplo anterior selecionamos dos indivíduos 3, 4 e 8 as variáveis de 3 a 5 (sexo, idade e escol).

Porém, os objetos do tipo data frames tem uma caracteristica diferente: o R automaticamente lê as colunas como variáveis. Então, podemos indicar as colunas a partir da sintaxe $. A função subset() nos ajuda a fazer filtragens mais avançadas:

subset(banco, banco$sexo == "m")
##    individuo raca sexo idade       escol renda    civil
## 17    000017    n    m    55       medio 23000   casado
## 18    000018    n    m    23       medio 19000   casado
## 19    000019    n    m    26       medio 26000   casado
## 20    000020    n    m    36       medio 18000   casado
## 21    000021    i    m    18       medio 30000    viuvo
## 22    000022    i    m    32       medio 12000    viuvo
## 23    000023    i    m    40       medio 13000 separado
## 24    000024    i    m    20       medio 28000 separado
## 25    000025    i    m    52       medio 23000 separado
## 26    000026    i    m    46 fundamental 27000 separado
## 27    000027    o    m    54 fundamental 24000 separado
## 28    000028    o    m    43 fundamental 28000 separado
## 29    000029    o    m    21 fundamental 23000 separado
## 30    000030    o    m    41 fundamental 17000 separado

Selecionamos no exemplo anterior apenas os casos que correspondem a seleção sexo == "m", ou seja, serem do sexo masculino. Podemos combinar filtragens do banco utilizando os operadores lógicos (& e |) e relacionais (> < >= <= != ==) já aprendidos anteriormente.

 
Exercício 3.26 Atribua a uma nova variável os indivíduos que tem idade menor que 35 anos e não tem nível superior.

 

A função subset() nos retorna os casos inteiros, mas as vezes apenas queremos saber quais casos correspondem a nossa filtragem. Podemos, então, utilizar a função which().

which(banco$escol != "superior" & banco$renda > 5000)
##  [1]  6  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Podemos, por fim, ordenar nosso banco a partir de uma variável desejada. Para isso, utilizamos a função order() e definimos no argumento se terá a ordem crescente ou decrescente. Essa função nos retorna um vetor com as posições das variáveis na ordem desejada. A partir desse vetor podemos criar um data frame novo.

ordem_nova <- order(banco$idade, decreasing = "F")

No comando anterior criamos um vetor com as posições que correspondem a ordem do nosso banco a partir da variável idade de forma crescente.

banco_ord <- banco[ordem_nova, ]

Agora temos um novo banco com a ordem desejada.

3.5 Listas

O último tipo de objeto que iremos ver são as listas, mas antes vamos recapitular os objetos que já vimos:

  • Vetores - são arrays de uma dimensão, podem ter valores numeric, character, logical, integer ou complex. Porém, os elementos dentro de um vetor sempre devem ter a mesma classe o vetor, portanto, herda essa classe.
  • Matrizes - são arrays de duas dimensões, podem ter valores numeric, character, logical, integer ou complex. São criadas a partir dos vetores portanto, herdam a mesma característica: elementos dentro de uma matriz tem sempre a mesma classe/tipo.
  • Data frames - objetos bidimensionais, podem ter valores numeric, character, logical, integer ou complex dentro de um mesmo objeto. Porém, os elementos de uma coluna devem ser do mesmo tipo de dado, mas colunas diferentes podem ter tipos diferentes de dados.

As listas, por sua vez, aceitam diferentes tipos de dado, de diferentes tamanhos, características. Podem armazenar objetos de forma ordenada, que podem ser matrizes, vetores, dataframes ou outras listas. Não é necessário que estejam ligados de alguma forma. Listas são um super data!

Para criar uma lista utilize a função list() e concatene dentro dos parênteses os objetos que quer colocar dentro da lista.