Aula baseada no livro: Introdução ao R capítulo 3. É sugerida a leitura do livro para um maior aprofundamento na linguagem de programação.

Objetos no R

Tudo no R é um objeto. Para atribuirmos resultados de operações a algum objeto que pode posteriormente ser manipulado, usamos a expressão de atribuição “<-”:

y <- 4
y
## [1] 4
x <- "ola"
x
## [1] "ola"

Observações:

  1. Recomenda-se o uso de nomes intuitivos, descritivos.

  2. Nomes de objetos não podem começar com números ou underline

# 2sls <- 45
# _1st_stage <- 1234
  1. Letras maiúsculas e minúsculas são diferentes para o interpretador do R

O R possui cinco classes básicas ou “atômicas” de objetos:

A função class(), aplicada a um objeto, retorna a sua classe.

class(x)
## [1] "character"
x <- 'ola'
class(x)
## [1] "character"
class(y)
## [1] "numeric"
y <- 2L
class(y)
## [1] "integer"
z <- TRUE
class(z)
## [1] "logical"
z <- z == y
class(z)
## [1] "logical"
c <- 1 + 1i
class(c)
## [1] "complex"

Valores especiais

NA, Inf, -Inf, e NaN

1/0
## [1] Inf
-1/0
## [1] -Inf
-Inf
## [1] -Inf
0/0
## [1] NaN
NA
## [1] NA

Podemos testar se uma expressão resulta em um valor especial

is.na(NA_real_)
## [1] TRUE
is.infinite(1/0)
## [1] TRUE
is.nan(0/0)
## [1] TRUE
is.nan(NA_character_)
## [1] FALSE
is.na(0/0)
## [1] TRUE

Vetores

São um conjunto unidimensional de valores de mesma classe

v <- c("arroz", "feijao")
v
## [1] "arroz"  "feijao"
class(v)
## [1] "character"
v <- c(v, 23) # append em um vetor
v
## [1] "arroz"  "feijao" "23"

Note que v transformou o numero 23 na string “23” e fez o append. Sem erro!

Vetores possuem tamanho (length)

length(v)
## [1] 3

Podemos usar também o operador : para criar sequências numéricas (que são armazenadas como vetores)

z <- 10:30
z
##  [1] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
class(z)
## [1] "integer"

Acessamos os elementos de um vetor através de seu índice

z[2]
## [1] 11

O último elemento de um vetor possui índice igual ao tamanho do vetor

z[length(z)]
## [1] 30

E podemos acessar um subconjunto do vetor através de uma sequência de índices

z[10:length(z)]
##  [1] 19 20 21 22 23 24 25 26 27 28 29 30

Índices negativos significam exclusão daquele elemento

z[-1] # retorna z com o primeiro elemento excluído
##  [1] 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
z[-c(1:5)] # retorna z sem os primeiros 5 elementos
##  [1] 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Para selecionarmos elementos de um vetor, podemos utilizar também uma expressão lógica, com os operadores == (igual), > (maior), < (menor), >= (maior ou igual), <= (menor ou igual), != (diferente), ou combinações de expressões lógicas por meio dos operadores booleanos “OU” (|), “E” (&), e “Não” (!).

z[z == 15]
## [1] 15
z[z < 15]
## [1] 10 11 12 13 14
z[z %in% c(12, 15, 31)]
## [1] 12 15
z[!(z %in% 15:25)]
##  [1] 10 11 12 13 14 26 27 28 29 30

Matrizes

Matrizes são vetores com um atributo de dimensão (dimension), que é ele próprio um vetor inteiro de tamanho 2: número de linhas e número de colunas. Uma matriz é criada por meio da função matrix(). Essa função possui os seguintes argumentos:

m <- matrix(data = 1:6, 
            nrow = 2, 
            ncol = 3, 
            byrow = TRUE, 
            dimnames = list(c("trat1", "trat2"), c("out1", "out2", "out3")))
m
##       out1 out2 out3
## trat1    1    2    3
## trat2    4    5    6

Para obtermos a dimensão de uma matriz, usamos a função dim.

dim(m)
## [1] 2 3

Outra maneira de se criar matrizes é pela adição de linhas ou colunas por meio das funções rbind() e cbind(), respectivamente. rbind() monta uma matriz, empilhando os argumentos linha a linha na ordem em que aparecem na lista. Já cbind() monta a matriz colocando os argumentos lado a lado na ordem em que aparecem na lista.

x <- 1:4
y <- 10:13
rbind(x, y)
##   [,1] [,2] [,3] [,4]
## x    1    2    3    4
## y   10   11   12   13
cbind(x, y)
##      x  y
## [1,] 1 10
## [2,] 2 11
## [3,] 3 12
## [4,] 4 13

Os elementos (células) de uma matriz podem ser acessados por um par de índices que indicam, respectivamente, a linha e a coluna do elemento desejado.

m[2, 3]
## [1] 6

Para extrairmos todos os elementos de uma linha, basta não especificarmos o índice correspondente à coluna.

m[2, ]
## out1 out2 out3 
##    4    5    6
m[, 2]
## trat1 trat2 
##     2     5

Note que a seleção de uma linha ou coluna retorna um vetor!

Índices negativos excluem os elementos indicados.

m[, -2] # matriz sem a segunda coluna
##       out1 out3
## trat1    1    3
## trat2    4    6

Podemos utilizar vetores de índices para selecionarmos uma submatriz.

m[, c(1, 3)]
##       out1 out3
## trat1    1    3
## trat2    4    6

Também podemos selecionar elementos de uma matriz através dos nomes das dimensões

m["trat1", "out3"]
## [1] 3

Listas

Listas são coleções de elementos que não precisam ser da mesma classe. As listas são os objetos mais versáteis no R. Os elementos de uma lista podem ser de qualquer tipo, inclusive outras listas. O tipo list é uma importante classe de objetos no R. Listas podem ser criadas explicitamente usando a função list().

x <- list(5, "kiwi", c(FALSE, TRUE, TRUE), 3 + 1i, 2L, m)
x
## [[1]]
## [1] 5
## 
## [[2]]
## [1] "kiwi"
## 
## [[3]]
## [1] FALSE  TRUE  TRUE
## 
## [[4]]
## [1] 3+1i
## 
## [[5]]
## [1] 2
## 
## [[6]]
##       out1 out2 out3
## trat1    1    2    3
## trat2    4    5    6
class(x)
## [1] "list"
length(x)
## [1] 6

Podemos extrair uma sub-lista usando colchetes simples e índices. Colchetes duplos são utilizados para extrair um elemento da lista. Neste caso o formato de retorno será o do elemento.

x[6] # retorna uma lista com um elemento (a matriz)
## [[1]]
##       out1 out2 out3
## trat1    1    2    3
## trat2    4    5    6
x[3:6] # retorno uma lista com os elementos de 3 a 6
## [[1]]
## [1] FALSE  TRUE  TRUE
## 
## [[2]]
## [1] 3+1i
## 
## [[3]]
## [1] 2
## 
## [[4]]
##       out1 out2 out3
## trat1    1    2    3
## trat2    4    5    6
x[[2]] # retorna o character "kiwi"
## [1] "kiwi"

Uma lista pode ser composta de elementos que são eles próprios uma lista ou vetores. Elementos de uma lista que pertence a outra lista são chamados elementos aninhados. Há duas maneiras de acessar um elemento aninhado de uma lista.

x[[c(3, 1)]] # extrai o 1º elemento do vetor que é o 3º elemento da lista
## [1] FALSE
x[[3]][1] # 3º elemento da lista, e então 1º elemento do vetor
## [1] FALSE

Elementos de uma lista podem ser nomeados (assim como em vetores)

x <- list(
    num = 5,
    char = "kiwi",
    vec = c(FALSE, TRUE, TRUE),
    comp = 3 + 1i,
    int = 2L,
    mat = m
)
x
## $num
## [1] 5
## 
## $char
## [1] "kiwi"
## 
## $vec
## [1] FALSE  TRUE  TRUE
## 
## $comp
## [1] 3+1i
## 
## $int
## [1] 2
## 
## $mat
##       out1 out2 out3
## trat1    1    2    3
## trat2    4    5    6

E agora podemos extrair estes elementos pelo nome

x$vec
## [1] FALSE  TRUE  TRUE
x[["vec"]]
## [1] FALSE  TRUE  TRUE
names(x)
## [1] "num"  "char" "vec"  "comp" "int"  "mat"

Data Frames

Data frames são utilizados para armazenar dados tabulados no R. Eles são usualmente criados quando lemos um arquivo de dados para ser analisado. Internamente no R, os data frames são representados como uma lista especial onde cada elemento da lista possui o mesmo tamanho. Cada elemento da lista pode ser interpretado como uma coluna e o tamanho de cada elemento da lista é o número de linhas ou observações. Como se trata de uma lista, as colunas de um data frame não precisam ser da mesma classe.

Um data frame pode ser criado explicitamente por meio da função data.frame(). Entretanto existem extensão ao data frame do base R, como por exemplo os tibbles (do pacote tibble que faz parte do tidyverse) e o data.table. Faremos bastante uso deste último nas aulas práticas.

pacientes <- data.frame(
    id = c("P1","P2","P3","P4"), 
    sexo = c("feminino", "feminino", "masculino", "masculino"), 
    pad = c(80, 85, 100, 95), pas = c(130, 140, 150, 145)
)
pacientes
##   id      sexo pad pas
## 1 P1  feminino  80 130
## 2 P2  feminino  85 140
## 3 P3 masculino 100 150
## 4 P4 masculino  95 145
names(pacientes)
## [1] "id"   "sexo" "pad"  "pas"

Cada coluna em um data.frame é nomeada e representa uma variável.

Os elementos de um data frame podem ser acessados como os elementos de uma lista ou de uma matriz. As variáveis podem ser identificadas pela sua posição no data frame.

pacientes$pad
## [1]  80  85 100  95
pacientes[3, 2]
## [1] "masculino"
pacientes[, c(2, 4)]
##        sexo pas
## 1  feminino 130
## 2  feminino 140
## 3 masculino 150
## 4 masculino 145
pacientes[, c("sexo", "pas")]
##        sexo pas
## 1  feminino 130
## 2  feminino 140
## 3 masculino 150
## 4 masculino 145
pacientes[, -c(1, 3)]
##        sexo pas
## 1  feminino 130
## 2  feminino 140
## 3 masculino 150
## 4 masculino 145
cols <- c("sexo", "pas")
pacientes[, cols]
##        sexo pas
## 1  feminino 130
## 2  feminino 140
## 3 masculino 150
## 4 masculino 145
pacientes[pacientes$sexo == "feminino", ]
##   id     sexo pad pas
## 1 P1 feminino  80 130
## 2 P2 feminino  85 140

Funções

Novas funcionalidades são adicionadas ao ambiente por meio da implementação de funções agrupadas em módulos ou pacotes. As funções no R possuem um nome seguido de zero ou mais argumentos entre parênteses. Vejamos alguns exemplos de funções.

x <- c(1, 4, 6, 1, 10) # cria um vetor contendo os números 1, 4, 6, 1 e 10
sort(x, decreasing = TRUE) # ordena x em ordem decrescente
## [1] 10  6  4  1  1
min(x) # menor valor de x
## [1] 1
sum(x)
## [1] 22
prod(x)
## [1] 240
mean(x)
## [1] 4.4
unique(x)
## [1]  1  4  6 10

Podemos também criar nossas próprias funções! Para criarmos uma função, usamos a palavra chave function seguida de uma lista de argumentos formais entre parênteses e separados por vírgulas. O código que é executado cada vez que a função é chamada aparece entre chaves.

twosam <- function(y1, y2) {
    n1  <- length(y1) 
    n2  <- length(y2)
    yb1 <- mean(y1)   
    yb2 <- mean(y2)
    s1  <- var(y1)    
    s2  <- var(y2)
    s <- ((n1 - 1)*s1 + (n2 - 1)*s2)/(n1 + n2 - 2)
    tst <- (yb1 - yb2)/sqrt(s*(1/n1 + 1/n2))
    
    return(tst)
}

a <- 1:10
b <- 3:12
twosam(a, b)
## [1] -1.477098