Introdução à linguagem R

Este texto apresenta a linguagem R, mostrando como ela pode ser usada para transformação de dados.

Variáveis e operações

O ambiente R inclui um console no qual pode-se digitar expressões e ver o resultado. Exemplo:

1 + 1
## [1] 2

Como em outras linguagens de programação, pode-se atribuir valores a variáveis. Em R, usa-se o operador de atribuição <-. Exemplo:

x <- 2
y <- 3
x + y
## [1] 5

Também podemos realizar comparações entre os valores. Exemplo:

x < y
## [1] TRUE
x == 9
## [1] FALSE

Vetores

R possui a estrutura vetor, que é uma lista de elementos do mesmo tipo. Pode-se criar um vetor com a função c. Exemplo (notas de 4 alunos em duas provas):

aluno <- c("Fulano", "Sicrano", "Beltrano", "Zutano")
prova <- c(4.8, 4.3, 5.7, 8.0)
trabalho <- c(6.5, 3.6, 6.8, 7.7)
prova
## [1] 4.8 4.3 5.7 8.0

Também pode-se criar um vetor com uma sequência de números usando :. Exemplo:

3:8
## [1] 3 4 5 6 7 8

Algumas operações com vetores:

# Somar um valor a todos os elementos do vetor
prova + 2
## [1]  6.8  6.3  7.7 10.0
# Somar os elementos correspondentes de dois vetores
prova + trabalho
## [1] 11.3  7.9 12.5 15.7
# Exemplo: tirar a média das duas provas
(prova + trabalho) / 2
## [1] 5.65 3.95 6.25 7.85
# Acessar o segundo elemento de um vetor
prova[2]
## [1] 4.3
# Acessar o segundo e o quarto elementos de um vetor
prova[c(2, 4)]
## [1] 4.3 8.0
# Comparar cada elemento com um valor específico
prova > 5
## [1] FALSE FALSE  TRUE  TRUE
# Acessar o terceiro e o quarto elementos de um vetor
prova[c(FALSE, TRUE, FALSE, TRUE)]
## [1] 4.3 8.0
# Podemos usar as abreviações T para TRUE e F para FALSE
prova[c(F, T, F, T)]
## [1] 4.3 8.0
# Acessar somente os elementos de um vetor maiores que 5
prova[prova > 5]
## [1] 5.7 8.0
# Identificar alunos com nota da prova superior a 5
aluno[prova > 5]
## [1] "Beltrano" "Zutano"
# Acessar a nota da prova do aluno chamado Sicrano
prova[aluno == 'Sicrano']
## [1] 4.3
# Identificador alunos com nota da prova superior a 5
# *ou* nota do trabalho superior a 5
aluno[prova > 5 | trabalho > 5]
## [1] "Fulano"   "Beltrano" "Zutano"
# Identificador alunos com nota da prova superior a 5
# *e* nota do trabalho superior a 5
aluno[prova > 5 & trabalho > 5]
## [1] "Beltrano" "Zutano"

Também podemos executar funções sobre os vetores:

# Comprimento do vetor (número de elementos)
length(prova)
## [1] 4
# Média entre os valores
mean(prova)
## [1] 5.7
# Soma dos valores
sum(prova)
## [1] 22.8
# Primeiros dois valores
head(prova, 2)
## [1] 4.8 4.3

Para consultar a documentação de uma função, digite ? seguido do nome da função. Exemplo:

?head

Valores faltando (NA)

Suponha que um dos alunos não fez o trabalho. Usamos a palavra especial NA para indicar valores que não existem ou cujo valor é desconhecido. Exemplo:

aluno <- c("Fulano", "Sicrano", "Beltrano", "Zutano")
prova <- c(4.8, 4.3, 5.7, 8.0)
trabalho <- c(NA, 3.6, 6.8, 7.7)
prova
## [1] 4.8 4.3 5.7 8.0

Nesse caso, qual a média das notas do trabalho?

mean(trabalho)
## [1] NA

Não é possível determinar a média dos 4 valores uma vez que um valor está faltando. Se quisermos ignorar os valores NA e tirar a média somente dos demais valores, devemos chamar a função mean passando o valor TRUE para o parâmetro na.rm:

mean(trabalho, na.rm=TRUE)
## [1] 6.033333

Data frames

Data frame é uma das estruturas de dados mais importantes do R, e se assemelha muito a uma tabela em um banco de dados ou a uma planilha com certas restrições. Um data frame é uma lista de vetores de mesmo tamanho, onde cada vetor possui um nome e representa uma coluna da tabela.

Geralmente os data frames são lidos a partir de arquivos CSV, xlsx ou outros formatos. O formato CSV é suportado nativamente peo R. Exemplo:

dados <- read.csv('data/tamanhos.txt')
dados
##        classe versao tamanho
## 1   Tela.java      1     235
## 2   Tela.java      3     311
## 3   Tela.java      2     288
## 4 Config.java      3      12
## 5 Config.java      2      23
## 6 Config.java      1      30

Podemos acessar colunas da tabela (i.e., vetores) usando $. Exemplo:

dados$tamanho
## [1] 235 311 288  12  23  30
mean(dados$tamanho)
## [1] 149.8333

Também podemos acessar elementos usando a notação [linha, coluna]. Exemplo:

# Acessa a primeira linha do data frame
dados[1, ]
##      classe versao tamanho
## 1 Tela.java      1     235
# Acessa a segunda coluna do data frame
dados[, 2]
## [1] 1 3 2 3 2 1
# Acessa o elemento na quarta linha, terceira coluna
dados[4, 3]
## [1] 12
# Acessa as 3 primeiras linhas, duas primeiras colunas
dados[1:3, 1:2]
##      classe versao
## 1 Tela.java      1
## 2 Tela.java      3
## 3 Tela.java      2
# Acessa as primeiras 3 linhas
dados[1:3, ]
##      classe versao tamanho
## 1 Tela.java      1     235
## 2 Tela.java      3     311
## 3 Tela.java      2     288
head(dados, 3)
##      classe versao tamanho
## 1 Tela.java      1     235
## 2 Tela.java      3     311
## 3 Tela.java      2     288

Algumas funções úteis para data frames:

# Primeiras 4 linhas
head(dados, 4)
##        classe versao tamanho
## 1   Tela.java      1     235
## 2   Tela.java      3     311
## 3   Tela.java      2     288
## 4 Config.java      3      12
# Últimas 4 linhas
tail(dados, 4)
##        classe versao tamanho
## 3   Tela.java      2     288
## 4 Config.java      3      12
## 5 Config.java      2      23
## 6 Config.java      1      30
# Número de linhas e colunas
nrow(dados)
## [1] 6
ncol(dados)
## [1] 3
# Sumário estatístico
summary(dados)
##          classe      versao        tamanho      
##  Config.java:3   Min.   :1.00   Min.   : 12.00  
##  Tela.java  :3   1st Qu.:1.25   1st Qu.: 24.75  
##                  Median :2.00   Median :132.50  
##                  Mean   :2.00   Mean   :149.83  
##                  3rd Qu.:2.75   3rd Qu.:274.75  
##                  Max.   :3.00   Max.   :311.00

Operações avançadas com a biblioteca dplyr

Se você ainda não o fez, instale a biblioteca dplyr:

install.packages('dplyr')

Para usar a biblioteca, use library:

library(dplyr)

Com a biblioteca dplyr, você pode escrever transformações de dados no seguinte formato:

dados %>% transformacao1(...) %>% transformacao2(...) %>% ...

O operador %>% é chamado de pipe (lê-se “páipe”). Ele pode ser pensado como um cano que transporta os dados do lado esquerdo para o lado direito até chegar no final.

O dplyr possui várias funções de transformação, como veremos a seguir.

filter (selecionar linhas)

Seleciona apenas as linhas de um data frame que satisfazem à condição fornecida. Exemplo: selecionar apenas as linhas em que a versao é igual a 1:

dados %>% filter(versao == 1)
##        classe versao tamanho
## 1   Tela.java      1     235
## 2 Config.java      1      30

Outro exemplo: selecionar apenas as linhas em que o tamanho é maior que 300 ou menor que 30:

dados %>%
  filter(tamanho > 300 | tamanho < 30)
##        classe versao tamanho
## 1   Tela.java      3     311
## 2 Config.java      3      12
## 3 Config.java      2      23

Note que pode-se inserir quebras de linha para deixar o código mais legível sem alterar o resultado.

arrange (ordenar linhas)

Com o arrange, você especifica as colunas que devem ser usadas na ordenação, em ordem de prioridade, usando desc para especificar ordem descendente. Exemplos:

dados %>%
  arrange(versao)
##        classe versao tamanho
## 1   Tela.java      1     235
## 2 Config.java      1      30
## 3   Tela.java      2     288
## 4 Config.java      2      23
## 5   Tela.java      3     311
## 6 Config.java      3      12
dados %>%
  arrange(classe, desc(tamanho))
##        classe versao tamanho
## 1 Config.java      1      30
## 2 Config.java      2      23
## 3 Config.java      3      12
## 4   Tela.java      3     311
## 5   Tela.java      2     288
## 6   Tela.java      1     235

Combinando as duas coisas:

dados %>%
  filter(classe == 'Tela.java') %>%
  arrange(versao)
##      classe versao tamanho
## 1 Tela.java      1     235
## 2 Tela.java      2     288
## 3 Tela.java      3     311

select (selecionar colunas)

Seleciona apenas as colunas especificadas. Exemplo:

dados %>%
  select(classe, tamanho)
##        classe tamanho
## 1   Tela.java     235
## 2   Tela.java     311
## 3   Tela.java     288
## 4 Config.java      12
## 5 Config.java      23
## 6 Config.java      30

mutate (criar colunas)

Com o mutate, pode-se criar novas colunas a partir das colunas existentes. Exemplo:

dados %>%
  mutate(produto = tamanho * versao,
         razao = tamanho / versao)
##        classe versao tamanho produto    razao
## 1   Tela.java      1     235     235 235.0000
## 2   Tela.java      3     311     933 103.6667
## 3   Tela.java      2     288     576 144.0000
## 4 Config.java      3      12      36   4.0000
## 5 Config.java      2      23      46  11.5000
## 6 Config.java      1      30      30  30.0000

sumarise (combinar todas as linhas em uma só)

Exemplos:

dados %>%
  summarise(tam_medio = mean(tamanho))
##   tam_medio
## 1  149.8333
dados %>%
  summarise(prod_max = max(tamanho * versao),
            versao_inicial = min(versao))
##   prod_max versao_inicial
## 1      933              1

Operações agrupadas com group_by

Você pode agrupar as linhas de acordo com os valores de uma ou mais colunas antes de aplicar o summarise.

dados %>%
  group_by(classe) %>%
  summarise(tam_medio = mean(tamanho))
## # A tibble: 2 × 2
##        classe tam_medio
##        <fctr>     <dbl>
## 1 Config.java  21.66667
## 2   Tela.java 278.00000