1. Conhecendo o R

Definindo o diretório de trabalho

setwd("caminho_da_pasta/separado/dessa_forma") # selecionando a pasta

getwd() # verifica qual é o atual diretório

Definindo um objeto

obj1=1 # obj1 recebe o inteiro '1'
obj1
## [1] 1
obj2="a" # obj2 recebe o caractere 'a' (sempre entre aspas simples ou composta)
obj2
## [1] "a"
obj3=T  # obj3 recebe o booleano 'TRUE' ('FALSE' pode ser feito com 'F')
obj3
## [1] TRUE
obj4="caderno vermelho" #obj4 recebe a string 'caderno vermelho'
obj4
## [1] "caderno vermelho"

Vetores, matrizes, data frames e listas

vetor1=c(1,2,3,4,5,6,7,8,9,10) # um vetor númerico formado por números de 1 a 10
vetor1
##  [1]  1  2  3  4  5  6  7  8  9 10
vetor2=1:10 # um vetor igual ao 'vetor1'
vetor2
##  [1]  1  2  3  4  5  6  7  8  9 10
vetor3=seq(from=11, to=20, by = 1) # sequencia de 11 a 20, de um a um
vetor3
##  [1] 11 12 13 14 15 16 17 18 19 20
matriz1=matrix(vetor2,ncol=2,byrow = F) 
# matrix numérica de 1 a 10, separado em 2 colunas ('ncol=2') e feita por coluna ('byrow=F' ou 'bycol=T')
matriz1
##      [,1] [,2]
## [1,]    1    6
## [2,]    2    7
## [3,]    3    8
## [4,]    4    9
## [5,]    5   10

Uma matriz é a composição de um ou mais vetores, e pode ser ou somente numérica ou somente de caracteres (a mistura dos dois tipos somente poderá ser um data frame).

df1=data.frame("Vetor_1"=letters[1:5],"Vetor_2"=c(1:5),stringsAsFactors = F) 
df1 
##   Vetor_1 Vetor_2
## 1       a       1
## 2       b       2
## 3       c       3
## 4       d       4
## 5       e       5
# 'StringAsFactor' é um booleano que indica se os vetores de caracteres serão fatores ou não
# Se 'T' (ou 'TRUE'), o 'Vetor_1' seria atribuído como fator, se 'F', continua como caractere
# letters é um objeto já existente no R, com o alfabeto em ordem crescente
lista1=list("Lista_Numerica"=seq(1,5,1),
            "Lista_Caracteres"=c("a","Uma","diablo","~~kfk~~","PSIU"))
lista1
## $Lista_Numerica
## [1] 1 2 3 4 5
## 
## $Lista_Caracteres
## [1] "a"       "Uma"     "diablo"  "~~kfk~~" "PSIU"
# uma lista pode ser composta só de vetores ou só de matrizes, quanto de vetores e matrizes, e até mesmo dataframes

lista1[[1]] # acessando a primeira lista da lista1
## [1] 1 2 3 4 5
lista1[[2]][1] # acessando o primeiro elemento da segunda lista da lista1
## [1] "a"

Geralmente, trabalharemos com data frames, que nada mais são que tabelas, em que cada coluna é um vetor. Ou seja, o R basicamente trabalha com vetores.

Operações com vetores e matrizes

Vetores

Premissa importante: todo vetor para o R é um vetor coluna.

Transpor um vetor

vetor4 = t(vetor1)
vetor4
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    1    2    3    4    5    6    7    8    9    10

Operações aritméticas de vetores

# Soma: Soma do elemento da posição i do vetor j com o da posição i do vetor k
vetor4 = vetor1+vetor3
vetor4
##  [1] 12 14 16 18 20 22 24 26 28 30
# Subtração: Diferença entre o elemento da posição i do vetor j e o da posição i do vetor k
vetor5 = vetor3-vetor1
vetor5
##  [1] 10 10 10 10 10 10 10 10 10 10
# Multiplicação: Multiplicação do elemento da posição i do vetor j pelo elemento da posição i do vetor k
vetor6 = vetor4*vetor5
vetor6
##  [1] 120 140 160 180 200 220 240 260 280 300
# Divisão: Divisão do elemento da posição i do vetor j pelo elemento da posição i do vetor k
vetor7 = vetor6/vetor5
vetor7
##  [1] 12 14 16 18 20 22 24 26 28 30
# Potência: cada elemento do vetor i elevado a potência m
vetor8 = vetor1^2
vetor8
##  [1]   1   4   9  16  25  36  49  64  81 100
# Raiz: raiz m de cada elemento do vetor i
vetor9 = vetor8^(1/2); sqrt(vetor8) # raiz quadrada 
##  [1]  1  2  3  4  5  6  7  8  9 10
vetor9
##  [1]  1  2  3  4  5  6  7  8  9 10
# Resto: Resto da divisão do elemento da posição i do vetor j pelo elemento da posição i do vetor k
vetor10 = vetor1%%vetor3
vetor10
##  [1]  1  2  3  4  5  6  7  8  9 10

Matrizes

Transpor uma matriz

matriz2 = t(matriz1)
matriz2
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    2    3    4    5
## [2,]    6    7    8    9   10

Operações aritméticas com matrizes

# Soma: Soma do elemento da posição (i,j) da matriz k com o elemento da posição (i,j) da matriz l. Tem que resultar em uma matriz da mesma dimensão das matrizes operadas.
matriz3 = matriz1+matriz1
matriz3
##      [,1] [,2]
## [1,]    2   12
## [2,]    4   14
## [3,]    6   16
## [4,]    8   18
## [5,]   10   20
# Subtração: Diferença do elemento da posição (i,j) da matriz k com o elemento da posição (i,j) da matriz l. Tem que resultar em uma matriz da mesma dimensão das matrizes operadas.
matriz4 = matriz3-matriz1
matriz4
##      [,1] [,2]
## [1,]    1    6
## [2,]    2    7
## [3,]    3    8
## [4,]    4    9
## [5,]    5   10
# Multiplicação: Multiplicação da linha i da matriz k com a coluna i da matriz l para gerar o elemento da posição (i,i). Feita com matrizes de dimensões transpostas. Resulta sempre em uma matriz quadrada (mesma quantidade de linhas e colunas).
matriz5 = matriz1%*%matriz2 # o operador %*% multiplica matrizes
matriz5
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   37   44   51   58   65
## [2,]   44   53   62   71   80
## [3,]   51   62   73   84   95
## [4,]   58   71   84   97  110
## [5,]   65   80   95  110  125
matriz1*matriz3 # aqui é a multiplicação elemento por elemento (as matrizes devem ter a mesma dimensão)
##      [,1] [,2]
## [1,]    2   72
## [2,]    8   98
## [3,]   18  128
## [4,]   32  162
## [5,]   50  200
5*matriz1 # multiplicação de uma matriz por um escalar
##      [,1] [,2]
## [1,]    5   30
## [2,]   10   35
## [3,]   15   40
## [4,]   20   45
## [5,]   25   50
# Divisão: Divisão do elemento da posição (i,j) da matriz k com o elemento da posição (i,j) da matriz l. Somente pode ser feita entre matrizes com mesma dimensão. Resulta sempre na mesma dimensão das matrizes operadas.
matriz6 = matriz1/matriz3
matriz6
##      [,1] [,2]
## [1,]  0.5  0.5
## [2,]  0.5  0.5
## [3,]  0.5  0.5
## [4,]  0.5  0.5
## [5,]  0.5  0.5
# Matriz diagonal: matriz identidade multiplicado por um escalar
matriz7 = diag(5,5,5) 
matriz7
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    5    0    0    0    0
## [2,]    0    5    0    0    0
## [3,]    0    0    5    0    0
## [4,]    0    0    0    5    0
## [5,]    0    0    0    0    5
# Determinante de uma matriz: Somente com matrizes quadradas
matriz8 = matrix(c(1,2,3,4),ncol=2)
det(matriz8)
## [1] -2
# Inversa de uma matriz: Somente com matrizes quadradas que tenham determinante
solve(matriz8)
##      [,1] [,2]
## [1,]   -2  1.5
## [2,]    1 -0.5
# Traço de uma matriz: Soma da diagonal de uma matriz
sum(diag(matriz8))
## [1] 5
# Autovalores e Autovetores
eigen(matriz8)
## eigen() decomposition
## $values
## [1]  5.3722813 -0.3722813
## 
## $vectors
##            [,1]       [,2]
## [1,] -0.5657675 -0.9093767
## [2,] -0.8245648  0.4159736

2. Condicionais: IF, ELSE

Os condicionais if e else são usados em conjunto.

if(df1$Vetor_1[1]=="a"){
  print(TRUE)
}else{
  print(FALSE)
}
## [1] TRUE
if(df1$Vetor_1[1]!="a"){
  print(TRUE)
}else{
  print(FALSE)
}
## [1] FALSE

No primeiro if/else do exemplo acima queremos saber se o elemento da primeira posição da coluna Vetor_1 do data frame df1 é igual a letra a. Se sim, fazer print(TRUE), ou seja, mostrar TRUE na tela. No segundo if/else do exemplo, é exatamente o oposto.

Ou seja, o if/else serve para executar uma ação com base em condições estabelecidas, e se essas condições não forem aceitas, fazer outra ação.

Caso a ação for apenas a condição explicitada no if, não necessariamente usamos o else. Veja:

if(df1$Vetor_1[1]=="a"){
  print(TRUE)
}
## [1] TRUE

Mesmo não tendo a função else, a ação mostrar na tela TRUE foi executada.

Loops: For, While

Os loops são utilizados para passear por vetores. Normalmente estão atrelados aos condicionais, para então executarem uma ação.

Obs: Há necessidade, muitas vezes, da utilização de operadores lógicos. São eles:

==: operador de comparação (igualdade)

!=: operador de comparação (desigualdade)

||: operador ou (união)

&&: operador e (intersecção)

>: maior que

<: menor que

>=: maior ou igual

<=: menor ou igual

# Vamos percorrer pelo vetor1
for(i in 1:length(vetor1)){
  print(vetor1[i])
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
# Vamos percorrer o mesmo vetor, mas agora tendo uma restrição
i=1
while (i<=5) {
  print(vetor1[i])
  i<-i+1
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5

Usando for, fazemos com que i vá de 1 ao tamanho do vetor1 (função length), e usamos o i de tal forma que mostre na tela o vetor1[1], vetor1[2]vetor1[10], incrementando de 1 em 1.

Usando while, dizemos que enquanto i for menor ou igual a 5, mostrar na tela vetor1[1], vetor1[2]vetor1[5], com incremento de 1. O seu incremento é com base no que colocamos no código.

i=1
while (i<=5) {
  print(vetor1[i])
  i<-i+2
}
## [1] 1
## [1] 3
## [1] 5

Loops aninhados

Chamamos de aninhados os loops com condicionais.

for(i in 1:length(vetor1)){
  if(vetor1[i]%%2==0){
    print(vetor1[i])
  }
}
## [1] 2
## [1] 4
## [1] 6
## [1] 8
## [1] 10

O exemplo acima “printa” na tela somente os valores pares do vetor1 (resto da divisão por 2 seja 0).

Faremos uma ação semelhante à função acima com a função ifelse, apenas com uma linha de código, entretanto será impresso o dividendo correspondente caso for par e 0 caso for ímpar.

ifelse(vetor1%%2==0,vetor1,0)
##  [1]  0  2  0  4  0  6  0  8  0 10

Funções

Podemos criar qualquer tipo de função, contanto que seja executável (sem erros de sintax).

Faremos aqui uma função em que o usuário tenha que responder pelo prompt.

ola1=function(){
  cat("Você está bem? (sim ou nao)\n")
  resp=scan(what = "character",n=1)
  if(resp=="sim"){
    cat("Que bom!")
  }else{
    cat("Você precisa dormir mais!")
  }
}

Outra forma de fazer a mesma função:

ola2=function(){
  print("Você está bem? (sim ou nao)\n")
  resp=readLines(n=1)
  if(resp=="sim"){
    print("Que bom!")
  }else{
    print("Você precisa dormir mais!")
  }
}

Faremos uma função que calcule a média de um vetor.

media=function(x){return(sum(x)/length(x))}
media(vetor1)
## [1] 5.5

As funções podem conter condicionais, loops e até loops aninhados. A próxima função mostrará na tela se um número é ímpar, par ou zero.

par_impar=function(x){
  if(x%%2==0 && x!=0){
    print("par")
  }
  if(x%%2!=0 && x!=0){
    print("ímpar")
  }
  if(x==0){
    print("zero")
  }
}
par_impar(3)
## [1] "ímpar"
par_impar(324)
## [1] "par"
par_impar(0)
## [1] "zero"

Boas práticas: Se houver necessidade de criar funções, é considerado boa prática fazer em outro arquivo e na criação ou tratamento de dados usar source() para chamar o arquivo .R que contém as funções.

3. Manipulação de dados

Verificar o tipo (classe) de cada coluna de um data frame

str(df1)
## 'data.frame':    5 obs. of  2 variables:
##  $ Vetor_1: chr  "a" "b" "c" "d" ...
##  $ Vetor_2: int  1 2 3 4 5

Acessar um valor de uma coluna específica de um data frame (vetor)

df1$Vetor_1 # selecionando a coluna 'Vetor_1'
## [1] "a" "b" "c" "d" "e"
df1[,1] # selecionando a primeira coluna
## [1] "a" "b" "c" "d" "e"
df1$Vetor_1[2] # acessando a linha 2 da coluna 'Vetor_1' 
## [1] "b"
df1[2,1] # acessando a linha 2 da coluna 1 ('Vetor_1')
## [1] "b"

Adicionar valores em um vetor

vetor1<-append(vetor1,6)
vetor1
##  [1]  1  2  3  4  5  6  7  8  9 10  6
vetor1<-append(vetor1,c(7,8,9,10))
vetor1
##  [1]  1  2  3  4  5  6  7  8  9 10  6  7  8  9 10
vetor1[c(11:15)]<-11:15 # usando 'append' ou apenas indicando o local onde cada elemento entrará no vetor
vetor1
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

Retirar valores de um vetor

vetor1<-vetor1[-c(6:15)] # para retirar valores de um vetor (ou matriz), basta usar '-' antes do local onde o elemento está
vetor1 
## [1] 1 2 3 4 5

Usando a mesma lógica para adicionar valores em um data frame

df1[6,]<-c("f",6)

Em um data frame, ao adicionar novos valores, adicionamos só a linha (ou coluna), ou seja, não podemos adicionar somente um elemento (ou célula).

OBS: um vetor pode ser somente de um tipo específico (não dá para ter números e caracteres em um mesmo vetor). Veja:

c("a",2,3,4,"e") # todos os elementos são caracteres, mesmo adicionando os inteiros como numéricos
## [1] "a" "2" "3" "4" "e"

Excluir valores de um data frame

df1<-df1[-6,] # excluindo toda a linha 6 
df1
##   Vetor_1 Vetor_2
## 1       a       1
## 2       b       2
## 3       c       3
## 4       d       4
## 5       e       5
df1[-5,1] # excluindo a linha 5 da primeira coluna
## [1] "a" "b" "c" "d"

Mesclar um vetor em outro

c(vetor1,vetor3)
##  [1]  1  2  3  4  5 11 12 13 14 15 16 17 18 19 20

Mesclar um data frame em outro

# Criando outro data frame
df2=data.frame("Vetor_1"=letters[6:10],"Vetor_2"=c(6:10),stringsAsFactors = F) 
df2 
##   Vetor_1 Vetor_2
## 1       f       6
## 2       g       7
## 3       h       8
## 4       i       9
## 5       j      10
# Mesclando por linha (É necessário que os dois data frames possuam a mesma quantidade de colunas, com os mesmos nomes)
df3=rbind(df1,df2)
df3
##    Vetor_1 Vetor_2
## 1        a       1
## 2        b       2
## 3        c       3
## 4        d       4
## 5        e       5
## 6        f       6
## 7        g       7
## 8        h       8
## 9        i       9
## 10       j      10

Uma mescla por coluna seria utilizando a função cbind, mas para fazer isso é necessário que ambos contenham o mesmo número de linhas.

Obs: É possível mesclar um vetor (coluna ou linha) em um data frame utilizando estas mesmas funções.

Acessar um banco de dados externo

Antes precisaremos instalar o pacote readxl para leitura de dados de planilha excel (xls,xlsx).

install.packages("readxl") # instala pacote

Não existe problema em instalar um pacote que já tenha sido instalado. A última instalação subscreverá a anterior. Mas para saber se possui um pacote em questão basta executar find.package("nome_do_pacote").

library(readxl) # chama o pacote da sua biblioteca

Lendo o arquivo ‘Demanda’, do tipo ‘xlsx’:

tabela=read_excel("Demanda.xlsx",col_types = c("date",rep("numeric",4)))
tabela
## # A tibble: 1,545 x 5
##    Periodo             Dia.Semana   Mes   Ano `Volume Real Tt`
##    <dttm>                   <dbl> <dbl> <dbl>            <dbl>
##  1 2014-07-01 00:00:00          3     7  2014          1268185
##  2 2014-07-02 00:00:00          4     7  2014          1202998
##  3 2014-07-03 00:00:00          5     7  2014          1432447
##  4 2014-07-04 00:00:00          6     7  2014          1187383
##  5 2014-07-05 00:00:00          7     7  2014          1205782
##  6 2014-07-07 00:00:00          2     7  2014          1223325
##  7 2014-07-08 00:00:00          3     7  2014          1389747
##  8 2014-07-09 00:00:00          4     7  2014          1496877
##  9 2014-07-10 00:00:00          5     7  2014          1572148
## 10 2014-07-11 00:00:00          6     7  2014          1535039
## # ... with 1,535 more rows

Tibble nada mais é que um data frame com uma melhor visualização.

str(tabela) # classes das colunas do data frame
## tibble[,5] [1,545 x 5] (S3: tbl_df/tbl/data.frame)
##  $ Periodo       : POSIXct[1:1545], format: "2014-07-01" "2014-07-02" ...
##  $ Dia.Semana    : num [1:1545] 3 4 5 6 7 2 3 4 5 6 ...
##  $ Mes           : num [1:1545] 7 7 7 7 7 7 7 7 7 7 ...
##  $ Ano           : num [1:1545] 2014 2014 2014 2014 2014 ...
##  $ Volume Real Tt: num [1:1545] 1268185 1202998 1432447 1187383 1205782 ...
colnames(tabela) # visualizo quais colunas o data frame possui
## [1] "Periodo"        "Dia.Semana"     "Mes"            "Ano"           
## [5] "Volume Real Tt"
head(tabela,5) # visualizo as 5 primeiras linhas do data frame
## # A tibble: 5 x 5
##   Periodo             Dia.Semana   Mes   Ano `Volume Real Tt`
##   <dttm>                   <dbl> <dbl> <dbl>            <dbl>
## 1 2014-07-01 00:00:00          3     7  2014          1268185
## 2 2014-07-02 00:00:00          4     7  2014          1202998
## 3 2014-07-03 00:00:00          5     7  2014          1432447
## 4 2014-07-04 00:00:00          6     7  2014          1187383
## 5 2014-07-05 00:00:00          7     7  2014          1205782
tail(tabela,5) # visualizo as 5 últimas linhas do data frame
## # A tibble: 5 x 5
##   Periodo             Dia.Semana   Mes   Ano `Volume Real Tt`
##   <dttm>                   <dbl> <dbl> <dbl>            <dbl>
## 1 2019-06-25 00:00:00          3     6  2019          1078119
## 2 2019-06-26 00:00:00          4     6  2019          1450389
## 3 2019-06-27 00:00:00          5     6  2019          1500218
## 4 2019-06-28 00:00:00          6     6  2019          1399839
## 5 2019-06-29 00:00:00          7     6  2019           952781

Sumário Estatístico

É possível, neste caso, verificar qual é a data inicial e a data final do banco de dados, bem como qual é o número máximo de semanas registrado no bd, ou qual é o volume mínimo e o máximo registrado, assim como sua média e mediana.

summary(tabela)
##     Periodo                      Dia.Semana         Mes              Ano      
##  Min.   :2014-07-01 00:00:00   Min.   :2.000   Min.   : 1.000   Min.   :2014  
##  1st Qu.:2015-09-30 00:00:00   1st Qu.:3.000   1st Qu.: 4.000   1st Qu.:2015  
##  Median :2017-01-03 00:00:00   Median :5.000   Median : 7.000   Median :2017  
##  Mean   :2016-12-30 15:39:29   Mean   :4.505   Mean   : 6.533   Mean   :2016  
##  3rd Qu.:2018-03-31 00:00:00   3rd Qu.:6.000   3rd Qu.:10.000   3rd Qu.:2018  
##  Max.   :2019-06-29 00:00:00   Max.   :7.000   Max.   :12.000   Max.   :2019  
##  Volume Real Tt   
##  Min.   :    182  
##  1st Qu.: 987587  
##  Median :1202998  
##  Mean   :1212538  
##  3rd Qu.:1424660  
##  Max.   :2788423

Medidas Descritivas

# Soma
sum(tabela$`Volume Real Tt`)
## [1] 1873371234
# Média
mean(tabela$`Volume Real Tt`)
## [1] 1212538
# Média ponderada: Um exemplo
pesos=c(0.25,0.50,0.25) # Soma = 1
tab=data.frame("UF"=c("BA","PE","MT"),"PMC"=c(90,85,94));tab
##   UF PMC
## 1 BA  90
## 2 PE  85
## 3 MT  94
weighted.mean(tab$PMC,pesos) # Média Ponderada do PMC das UFs
## [1] 88.5
# Mediana
median(tabela$`Volume Real Tt`)
## [1] 1202998
# Variância
var(tabela$`Volume Real Tt`)
## [1] 138192518384
# Desvio Padrão (Mesma grandeza dos dados)
sd(tabela$`Volume Real Tt`) # ou sqrt(var)
## [1] 371742.5
# Valor Mínimo
min(tabela$`Volume Real Tt`)
## [1] 182
# Valor Máximo
max(tabela$`Volume Real Tt`)
## [1] 2788423
# Quartis: Dividir os dados em 25, 50 (mediana) e 75%
quantile(tabela$`Volume Real Tt`,probs=c(0.25,0.50,0.75)) 
##     25%     50%     75% 
##  987587 1202998 1424660
## Moda: Não existe função própria no R, mas um exemplo de como fazê-lo
data(cars)
cars$speed # os dados já estão ordenados (para ordenar um vetor, usar função 'sort') 
##  [1]  4  4  7  7  8  9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15
## [26] 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24 24 24 24 25
freq = table(cars$speed);freq # obtém a tabela com frequência dos elementos
## 
##  4  7  8  9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 
##  2  2  1  1  3  2  4  4  4  3  2  3  4  3  5  1  1  4  1
names(table(cars$speed))[table(cars$speed) == max(table(cars$speed))]# obtém qual elemento aparece mais (moda)
## [1] "20"
# Outra forma de calcular a moda
moda<-function(x){return(names(sort(-table(as.vector(x))))[1])}
moda(cars$speed)
## [1] "20"

Família Apply

As funções da família Apply permitem que façamos várias operações sobre vetores.

apply: aplica uma função nas linhas ou colunas de uma tabela e retorna um vetor

apply(X = tabela[,-1],MARGIN = 2,FUN = "sum") # aplicando a soma(FUN="sum") por coluna (MARGIN=2)
##     Dia.Semana            Mes            Ano Volume Real Tt 
##           6960          10094        3115489     1873371234

lapply: aplica uma função em cada elemento de uma lista e retorna uma lista

lista2=list(a=1:10,b=11:20,c=21:30)
lapply(X=lista2,FUN="mean")
## $a
## [1] 5.5
## 
## $b
## [1] 15.5
## 
## $c
## [1] 25.5

sapply: aplica uma função em cada elemento de uma lista e retorna um vetor

sapply(X=lista2,FUN="sd")
##       a       b       c 
## 3.02765 3.02765 3.02765

mapply: aplica uma função em diferentes estruturas (vetor, matriz, etc.) de elemento em elemento.

mapply("sum",vetor1,vetor2) # o vetor1 tem tamanho 5 e o vetor2 tem tamanho 10, logo foi somado os elementos de 1 a 5 de ambos e os elementos restantes do vetor2 foram repetidos
##  [1]  2  4  6  8 10  7  9 11 13 15

tapply: aplica uma função em um vetor que está definido por outro vetor

x=1:20
y=factor(rep(letters[1:5],4))
tapply(x,y,FUN="sum") 
##  a  b  c  d  e 
## 34 38 42 46 50

Selecionar dados específicos (Filtros)

Selecionar determinada informação pode ser custoso diretamente na base do R. Por exemplo, quero selecionar qual foi o volume de todos os meses de Abril. Usando a base do R faríamos:

tabela$`Volume Real Tt`[tabela$Mes==4]
##   [1] 1331913 1539774  682779  960889 1378834 1469180 1474092 1441551 1179019
##  [10] 1133140 1424746 1501562 1560327 1561032 1324994 1509249   66530 1735563
##  [19] 1707474 1840708 1563914 1383993 2051720 2151474 2788423  942663  919502
##  [28]  776296 1093186 1241803 1321381 1314603 1188492  971654 1218538 1334133
##  [37] 1302426 1344691 1022135 1081720 1316609 1499411 1350826 1146109 1081155
##  [46] 1259794 1505372 1464004 1557210 1696972  456504  356669  717957  903764
##  [55]  846413  950622  752012  845006 1238275 1326383 1260852    5727  636963
##  [64]  884076 1192642 1410272 1380747  130793 1059854 1019881 1359100 1492842
##  [73] 1456617 1444493 1252412  144546  950957 1057762 1119035 1049476  835861
##  [82]  797957  996534 1132330 1091259 1006510  823905  837064 1066871 1144376
##  [91] 1167862 1130779    3282 1140393 1158796 1318647 1202444 1266035  971920
## [100] 1035702  582989  869226  879801  907282  957945  714122  685021 1109899
## [109] 1098980 1132921 1049811  782670  804080 1277500 1344211 1209850   12265
## [118]  797058  944604 1119783 1258777 1174808 1166129  984558 1035335 1385376

Existe um pacote que nos auxilia a resolver esse tipo de problema de forma mais intuitiva, o pacote dplyr. Veja como seria fazer o mesmo filtro utilizando este pacote:

library(dplyr)

tabela %>% select(`Volume Real Tt`,Mes) %>% filter(Mes==4)
## # A tibble: 126 x 2
##    `Volume Real Tt`   Mes
##               <dbl> <dbl>
##  1          1331913     4
##  2          1539774     4
##  3           682779     4
##  4           960889     4
##  5          1378834     4
##  6          1469180     4
##  7          1474092     4
##  8          1441551     4
##  9          1179019     4
## 10          1133140     4
## # ... with 116 more rows

O operador %>% é utilizado para substituir o uso do parâmetro que define qual objeto será selecionado para o uso das funções. Normalmente é o primeiro parâmetro das funções.

Verficando qual é o dia da semana com o maior registro de volume e quando ocorreu.

tabela %>% select(Periodo,Dia.Semana,`Volume Real Tt`) %>% filter(`Volume Real Tt`==max(`Volume Real Tt`))
## # A tibble: 1 x 3
##   Periodo             Dia.Semana `Volume Real Tt`
##   <dttm>                   <dbl>            <dbl>
## 1 2015-04-30 00:00:00          5          2788423

Assim, podemos ver que 30/04/2015 foi o dia de maior volume registrado entre julho/14 e junho/19.

Validação de Dados

# Criando tabela hipotética de volume mensal por marca antes da atualização
tab1=data.frame("Periodo"=rep(seq(as.Date("2019-01-01"),as.Date("2019-06-01"),"month"),2),"Volume"=c(265447,225361,235695,245632,245871,236587,152632,125413,136585,145258,145263,144325),"Marca"=c(rep("Coca-cola",6),rep("Fanta",6)));tab1
##       Periodo Volume     Marca
## 1  2019-01-01 265447 Coca-cola
## 2  2019-02-01 225361 Coca-cola
## 3  2019-03-01 235695 Coca-cola
## 4  2019-04-01 245632 Coca-cola
## 5  2019-05-01 245871 Coca-cola
## 6  2019-06-01 236587 Coca-cola
## 7  2019-01-01 152632     Fanta
## 8  2019-02-01 125413     Fanta
## 9  2019-03-01 136585     Fanta
## 10 2019-04-01 145258     Fanta
## 11 2019-05-01 145263     Fanta
## 12 2019-06-01 144325     Fanta
# Tabela depois da atualização
tab2=data.frame("Periodo"=rep(seq(as.Date("2019-01-01"),as.Date("2019-06-01"),"month"),2),"Volume"=c(265447,225365,235689,245632,245874,236590,152630,125402,136585,145258,145262,144329),"Marca"=c(rep("Coca-cola",6),rep("Fanta",6)));tab2
##       Periodo Volume     Marca
## 1  2019-01-01 265447 Coca-cola
## 2  2019-02-01 225365 Coca-cola
## 3  2019-03-01 235689 Coca-cola
## 4  2019-04-01 245632 Coca-cola
## 5  2019-05-01 245874 Coca-cola
## 6  2019-06-01 236590 Coca-cola
## 7  2019-01-01 152630     Fanta
## 8  2019-02-01 125402     Fanta
## 9  2019-03-01 136585     Fanta
## 10 2019-04-01 145258     Fanta
## 11 2019-05-01 145262     Fanta
## 12 2019-06-01 144329     Fanta
# Sumarização da primeira tabela
gp1=tab1%>%group_by(Marca)%>%summarise(Vol_Medio_Anterior=mean(Volume));gp1
## # A tibble: 2 x 2
##   Marca     Vol_Medio_Anterior
##   <chr>                  <dbl>
## 1 Coca-cola            242432.
## 2 Fanta                141579.
# Sumarização da segunda tabela
gp2=tab2%>%group_by(Marca)%>%summarise(Vol_Medio_Posterior=mean(Volume));gp2
## # A tibble: 2 x 2
##   Marca     Vol_Medio_Posterior
##   <chr>                   <dbl>
## 1 Coca-cola             242433.
## 2 Fanta                 141578.
# Verificando se as tabelas estão com os mesmos valores
gp=cbind(gp1,gp2[,2])
gp<-gp%>%select(Marca,Vol_Medio_Anterior,Vol_Medio_Posterior)%>%mutate("Diferença"=Vol_Medio_Anterior-Vol_Medio_Posterior);gp
##       Marca Vol_Medio_Anterior Vol_Medio_Posterior  Diferença
## 1 Coca-cola           242432.2            242432.8 -0.6666667
## 2     Fanta           141579.3            141577.7  1.6666667

A função summarise é utilizada para resumir os dados de acordo com a variável selecionada para agrupamento, usando a função group_by, e uma função a qual deseja-se sumarizar. No caso em questão, resumimos o volume pela média de cada marca dentro do período das tabelas.

Já a função mutate serve para mudar uma tabela já existente, acrescentando uma coluna em função de outra(s) coluna(s), em que no exemplo, utilizamos a função para criar uma coluna com a diferença das duas colunas de volume médio anterior e posterior à atualização.

Ordenação de dados

Um exemplo para a esta situação seria ordenar o volume em ordem decrescente (ou crescente). Veja como seria

tab3 = tabela %>% select(Periodo,`Volume Real Tt`) %>% arrange(-`Volume Real Tt`);tab3 
## # A tibble: 1,545 x 2
##    Periodo             `Volume Real Tt`
##    <dttm>                         <dbl>
##  1 2015-04-30 00:00:00          2788423
##  2 2014-12-30 00:00:00          2584947
##  3 2014-12-23 00:00:00          2433226
##  4 2014-12-19 00:00:00          2409500
##  5 2014-12-29 00:00:00          2341274
##  6 2016-12-30 00:00:00          2334924
##  7 2014-12-31 00:00:00          2314538
##  8 2014-11-28 00:00:00          2300092
##  9 2014-12-18 00:00:00          2278882
## 10 2014-12-27 00:00:00          2270514
## # ... with 1,535 more rows
# Para fazer em ordem crescente basta retirar o sinal de menos

Vemos que o dia 30 de abril de 2015 pode ser considerado um dia atípico, dado o fato de que todos os dias logo abaixo dele são de dezembro de 2014.

Transformação dos dados

Para agilizarmos esse processo utilizaremos o pacote tidyr.

library(tidyr)

Transformar colunas em linhas

Usaremos um exemplo de um bd da base do R. Para carregar qualquer bd do diretório do R basta usar o comando data("nome do bd").

data("USArrests")
head(USArrests)
##            Murder Assault UrbanPop Rape
## Alabama      13.2     236       58 21.2
## Alaska       10.0     263       48 44.5
## Arizona       8.1     294       80 31.0
## Arkansas      8.8     190       50 19.5
## California    9.0     276       91 40.6
## Colorado      7.9     204       78 38.7

São dados dos Estados Unidos sobre crimes acontecidos numa determinada época. Faremos o seguinte: Iremos transformar a tabela em questão numa tabela transversal, em que as variáveis estarão em uma coluna e os valores em outra, variando apenas o estado.

USArrests$State <- rownames(USArrests)  # criando uma coluna com os nomes dos estados
head(USArrests)
##            Murder Assault UrbanPop Rape      State
## Alabama      13.2     236       58 21.2    Alabama
## Alaska       10.0     263       48 44.5     Alaska
## Arizona       8.1     294       80 31.0    Arizona
## Arkansas      8.8     190       50 19.5   Arkansas
## California    9.0     276       91 40.6 California
## Colorado      7.9     204       78 38.7   Colorado
usa.long = USArrests %>% gather(key="Crime", value="Valor",-State )
head(usa.long)
##        State  Crime Valor
## 1    Alabama Murder  13.2
## 2     Alaska Murder  10.0
## 3    Arizona Murder   8.1
## 4   Arkansas Murder   8.8
## 5 California Murder   9.0
## 6   Colorado Murder   7.9

Assim, Crime é uma variável categórica, tendo os fatores Murder, Assault, UrbanPop e Rape. Já a variável Valor é uma variável numérica. Cada State tem o registro de qual crime aconteceu e quantos foram.

Para fazer o inverso, transformar linhas em colunas, basta utilizar a função spread.

usa.wide = usa.long %>% spread(key="Crime", value="Valor")
head(usa.wide)
##        State Assault Murder Rape UrbanPop
## 1    Alabama     236   13.2 21.2       58
## 2     Alaska     263   10.0 44.5       48
## 3    Arizona     294    8.1 31.0       80
## 4   Arkansas     190    8.8 19.5       50
## 5 California     276    9.0 40.6       91
## 6   Colorado     204    7.9 38.7       78

Dividir uma variável em duas

Utilizada quando se tem duas informações em uma mesma variável. Usaremos a tabela Demanda como exemplo, dividindo o Periodo em dia, mês e ano. Esta função permite apenas divisão de uma variável em duas, e como temos 3 informações na variável Periodo, temos que antes fazer um procedimento para que a informação do dia não seja excluída.

library(stringr)
tabela$Periodo <- str_replace(tabela$Periodo,"-","/")
head(tabela$Periodo)
## [1] "2014/07-01" "2014/07-02" "2014/07-03" "2014/07-04" "2014/07-05"
## [6] "2014/07-07"

No procedimento acima, utilizamos o pacote stringr, utilizado para manipulação de strings (veremos logo mais), para podermos substituir o primeiro - por /, para então dividirmos a coluna Periodo em duas, sem perder a informação do dia.

tab4 = tabela %>% select(Periodo,`Volume Real Tt`) %>% separate(Periodo,sep="/",into = c("Ano","Mês"))
head(tab4)
## # A tibble: 6 x 3
##   Ano   Mês   `Volume Real Tt`
##   <chr> <chr>            <dbl>
## 1 2014  07-01          1268185
## 2 2014  07-02          1202998
## 3 2014  07-03          1432447
## 4 2014  07-04          1187383
## 5 2014  07-05          1205782
## 6 2014  07-07          1223325

Então agora podemos dividir a coluna Mês em duas: Mês e Dia.

tab5 = tab4 %>% separate(`Mês`,sep="-",into = c("Mês","Dia"))
head(tab5)
## # A tibble: 6 x 4
##   Ano   Mês   Dia   `Volume Real Tt`
##   <chr> <chr> <chr>            <dbl>
## 1 2014  07    01             1268185
## 2 2014  07    02             1202998
## 3 2014  07    03             1432447
## 4 2014  07    04             1187383
## 5 2014  07    05             1205782
## 6 2014  07    07             1223325

Voltando agora o separador da variável Periodo da tabela.

tabela$Periodo <- str_replace(tabela$Periodo,"/","-")
head(tabela$Periodo)
## [1] "2014-07-01" "2014-07-02" "2014-07-03" "2014-07-04" "2014-07-05"
## [6] "2014-07-07"

Unir duas variáveis em uma

Vamos fazer exatamente o oposto do que fizemos anteriormente, até chegarmos na variável Periodo.

Primeiro, uniremos as colunas Mês e Dia, depois uniremos com o Ano e teremos a coluna Periodo novamente.

tab6 = tab5 %>% unite("Mes_Dia","Mês","Dia",sep="-")
head(tab6)
## # A tibble: 6 x 3
##   Ano   Mes_Dia `Volume Real Tt`
##   <chr> <chr>              <dbl>
## 1 2014  07-01            1268185
## 2 2014  07-02            1202998
## 3 2014  07-03            1432447
## 4 2014  07-04            1187383
## 5 2014  07-05            1205782
## 6 2014  07-07            1223325
tab7 = tab6 %>% unite("Periodo","Ano","Mes_Dia",sep="-")
head(tab7)
## # A tibble: 6 x 2
##   Periodo    `Volume Real Tt`
##   <chr>                 <dbl>
## 1 2014-07-01          1268185
## 2 2014-07-02          1202998
## 3 2014-07-03          1432447
## 4 2014-07-04          1187383
## 5 2014-07-05          1205782
## 6 2014-07-07          1223325

Remover duplicatas

De um vetor de strings

vect1=c("maçã","amora","goiaba","maçã","goiaba","mamão")
vect2=unique(vect1)
vect2
## [1] "maçã"   "amora"  "goiaba" "mamão"

De uma tabela

tab8=data.frame("x"=c(1,1,4,5,3,3,6),
       "y"=c(2,2,2,2,2,2,2))
distinct(tab8,x,.keep_all = T)
##   x y
## 1 1 2
## 2 4 2
## 3 5 2
## 4 3 2
## 5 6 2

4. Manipulação de Strings

O pacote principal para manipulação de strings é o stringr, que mostrei a vocês no bloco anterior. Mostrarei algumas funcionalidades.

Obs: Para ver todas as funções de um pacote, basta digitar nome_do_pacote:: e apertar a tecla Tab no RStudio. Você conseguirá ver não só as funções, como também o resumo do Help (parâmetros, descrição dos parâmetros, etc.). Para ver o Help completo, basta executar o comando ?função_ou_pacote.

Extrair parte de uma string

# Exemplo de string
st1="Quem canta os males espanta."
# Extraindo o sobrenome
st2=str_sub(st1,start=12)
st2
## [1] "os males espanta."
# Forma otimizada
st3=str_sub(st1,str_locate(st1,"o")[1])
st3
## [1] "os males espanta."

A função acima extrai uma string com base na posição que o primeiro caractere se encontra na string anterior. Obs: O espaço também é um caractere.

Como foi extraído a última string do objeto st1, bastou-se utilizar o parâmetro start. Entretando se a opção é extrair no meio do objeto, deve-se utilizar o parâmetro end.

Existe uma outra função, semelhante a esta: str_extract, porém extrai apenas os caracteres colocados como parâmetro.

str_extract(st1,"os males espanta")
## [1] "os males espanta"

Trabalhar com strings necessita o conhecimento do que é REGEX, ou Expressões Regulares, que são notações para representar padrões em strings. Obs: Para mais informações, acesse http://turing.com.br/material/regex/introducao.html .

Substituir caracteres de uma string

Vimos um exemplo disto no bloco anterior, entretando vamos rever para melhor fixação.

# Exemplo 1
st4=c("onde tiver amor, haverá paz")
st4
## [1] "onde tiver amor, haverá paz"
# Substituindo o 'á' por 'a'
st5=str_replace(st4,"á","a")
st5
## [1] "onde tiver amor, havera paz"
# Exemplo 2
st6=c("quero sorvete e chocolate")
st6
## [1] "quero sorvete e chocolate"
# Substituindo 'sorvete' por 'açaí'
st7=str_replace(st6,"sorvete","açaí")
st7
## [1] "quero açaí e chocolate"
# Exemplo 3
st8=c("três pratos de trigo para três tigres tristes")
st8
## [1] "três pratos de trigo para três tigres tristes"
# Substituindo todas as repetições de 'três' por 'quatro'
st9=str_replace_all(st8,"três","quatro")
st9
## [1] "quatro pratos de trigo para quatro tigres tristes"

A função str_replace_all faz a mesma coisa que a função str_replace, mas para todas as vezes em que a string, ou caractere, se repetir.

Remover caracteres de uma string

st10=str_remove(st7,"açaí e ")
st10
## [1] "quero chocolate"
st11=str_remove_all(st9,"quatro ")
st11
## [1] "pratos de trigo para tigres tristes"

Detectar a presença de um caractere em uma string

st12=c("Adam","Bruno","Camila","Daniel","Helena","Vitória")
st13=c("Adam","Daniel","Helena","Vitória","Sabrina","Samuel")
str_detect(st12,st13)
## [1]  TRUE FALSE FALSE FALSE FALSE FALSE

Nessa situação, a função está detectando se os elementos da mesma posição de st12 e st13 são iguais. Mas vemos que Daniel está presente nos dois vetores, assim como Helena e Vitória. Faremos então com que a função str_detect verifique se os nomes de um vetor estão ou não no outro vetor, através de um loop for.

for(i in 1:length(st12)){
  for(j in 1:length(st13)){
    if(str_detect(st12[i],st13[j])==TRUE){
          print(st13[j])
    }
  }
}
## [1] "Adam"
## [1] "Daniel"
## [1] "Helena"
## [1] "Vitória"

Guardando em um vetor seria:

st14=vector()
for(i in 1:length(st12)){
  for(j in 1:length(st13)){
    if(str_detect(st12[i],st13[j])==TRUE){
          st14<-append(st14,st13[j])
    }
  }
}
st14
## [1] "Adam"    "Daniel"  "Helena"  "Vitória"

Separar uma string

# Separando a string 'st1' em duas
st1
## [1] "Quem canta os males espanta."
st15=str_split(st1," ",simplify = T) # simplify = T indica que queremos que a string seja "splitada" em uma matriz (Se F, seria uma lista)
st15
##      [,1]   [,2]    [,3] [,4]    [,5]      
## [1,] "Quem" "canta" "os" "males" "espanta."

Temos agora ao invés de uma string com a frase inteira, 5 strings em um vetor. Entretanto, a função str_split transforma o vetor em uma lista por default, mas como utilizamos o parâmetro simplify = T, temos uma matriz 1x5. Para transformar em um vetor, basta utilizar o comando as.vector(objeto).

st15<-as.vector(st15)
st15
## [1] "Quem"     "canta"    "os"       "males"    "espanta."

Capitalize

st16=c("AQUI SOMOS UM")
# Tornar todas as letras da string minúsculas
st17=str_to_lower(st16)
st17
## [1] "aqui somos um"
# Tornar todas as letras da string maiúsculas
st18=str_to_upper(st17)
st18
## [1] "AQUI SOMOS UM"
# Tornar a primeira letra de cada string maiúscula
st19=str_to_title(st17)
st19
## [1] "Aqui Somos Um"
# Tornar a primeria letra da primeira string maiúscula
st20=str_to_sentence(st19)
st20
## [1] "Aqui somos um"

Concatenar strings

A função que utilizaremos para concatenar strings faz parte da base do R, é a função paste.

vetor11 = "a história é a seguinte:"
vetor12="era uma vez aquilo lá!"
paste(vetor11,vetor12,sep=" ") #fazendo com separador
## [1] "a história é a seguinte: era uma vez aquilo lá!"
paste0(vetor11,vetor12) #fazendo sem separador
## [1] "a história é a seguinte:era uma vez aquilo lá!"

5. Juntar os dados

Muitas vezes, temos a necessidade de juntar duas planilhas, cujo alguns valores são os mesmos. Por exemplo, uma planilha que já tenhamos com informações passadas de volume por SKU e queremos atualizar ela com base em uma planilha vindo direto da UXT com novas colunas, também por SKU.

Simplesmente mesclando da forma que mostrei anteriormente não resolveria o problema porque teríamos uma mesma SKU repetida. Nesse caso, a ferramenta a ser mostrada resolveria este problema.

Irei apresentar a função full_join com base em um bd já existente no R.

band_members
## # A tibble: 3 x 2
##   name  band   
##   <chr> <chr>  
## 1 Mick  Stones 
## 2 John  Beatles
## 3 Paul  Beatles
band_instruments
## # A tibble: 3 x 2
##   name  plays 
##   <chr> <chr> 
## 1 John  guitar
## 2 Paul  bass  
## 3 Keith guitar
band_members %>% full_join(band_instruments,by=c("name"="name"))
## # A tibble: 4 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 Mick  Stones  <NA>  
## 2 John  Beatles guitar
## 3 Paul  Beatles bass  
## 4 Keith <NA>    guitar

Usando essa função, juntamos todas as informações das planilhas, tendo elas as mesmas colunas ou não. Neste exemplo a chave das duas tabelas está com o mesmo nome name, entretanto existem situações em que apenas os nomes diferem, mas as informações são as mesmas. Por isso usar o parâmetro by, que é onde indicamos qual é a chave de cada planilha.

Para juntar somente as mesmas informações das chaves, utilizaremos a função inner_join.

band_members %>% inner_join(band_instruments,by=c("name"="name"))
## # A tibble: 2 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 John  Beatles guitar
## 2 Paul  Beatles bass

Para mantermos os dados do conjunto a esquerda e os registros a direita que coincidirem com a chave usamos a função left_join.

band_members %>% left_join(band_instruments,by=c("name"="name"))
## # A tibble: 3 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 Mick  Stones  <NA>  
## 2 John  Beatles guitar
## 3 Paul  Beatles bass

Para fazermos o contrário, usamos a função right_join.

band_members %>% right_join(band_instruments,by=c("name"="name"))
## # A tibble: 3 x 3
##   name  band    plays 
##   <chr> <chr>   <chr> 
## 1 John  Beatles guitar
## 2 Paul  Beatles bass  
## 3 Keith <NA>    guitar

Fim!