1 Introdução

Esta página destina-se aqueles que desejam aprender a utilizar o RStudio de forma rápida, como ferramenta de trabalho ou acadêmica. Para deixar a explicação mais leve, muitos conceitos que fundamentam a programação não serão abordados. Além do texto, serão disponibilizados vídeos curtos.

1.1 O R e tutorial de instalação do R e do RStudio

A Linguagem R foi criada em 1991 por Ross Ihaka e Robert Gentleman no Departamento de Estatística da Universidade de Auckland, na Nova Zelândia. Ela é derivado da linguagem comercial S desenvolvida nos Bell Labs na década de 1970, o que lhe confere uma base sólida e intrínseca para a computação estatística e gráfica.
Em 1993 houve o anúncio público do R que enfrentava fárias restrições por ser derivada de uma linguagem comercializada. Por causa desse problema, seus criadores decidiram adotar o GNU General Public License, tornando o R um software livre. Isso permitiu que a linguagem fosse amplamente utilizada e desenvolvida pela comunidade, tendo a sua primeria versão (1.0.0) sido lançada em 2000.
Essa herança significa que o R foi projetado desde o início com estatísticos e pesquisadores em mente, incorporando estruturas de dados e funções otimizadas para manipulação, análise e visualização de dados de forma nativa. Sua sintaxe facilita as operações matriciais e vetoriais, comuns em estatística. Isso o torna uma ferramenta robusta e flexível para desenvolvimento de novos métodos estatísticos, simulações e análise de dados, sendo amplamente adotado em universidades e centros de pesquisa.
Atualmente, o R é oferecido de forma gratuita a partiri dos Comprehensive R Archive Network (CRAN) e é compatível com sistemas operacionais como Linux, Mac e Windows, além de poder ser operado diretamente na nuvem.  Uma grande comunidade ativa oferece suporte, documentação e recursos de aprendizado abundantes que aliada à sua arquitetura de pacotes permite o desenvolvimento de funcionalidades especializadas, tornando o R adaptável a praticamente qualquer domínio de análise (econometria, bioinformática, aprendizado de máquina, etc.), o que o tornou um software com Capacidades Gráficas Avançadas, com ferramentas poderosas para visualização de dados, desde gráficos básicos até visualizações interativas complexas.
O RStudio é um Ambiente de Desenvolvimento Integrado (IDE), também ofertado gratuitamente, que oferece ferramentas para aumentar a produtividade dos desenvolvedores. Também possui versões pagas que disponibilizam mais recursos.

Antes da instalação do RStudio, é necessário instalar o R.
A instalação do R é simples e é possível a partir dos links:
Repositório geral
R para Windows
R para Mac
R para linux

O R dispõe de ampla documentação que pode ser encontrada em:
Perguntas e respostas  

De forma similar, a instalação do RStudio é simples. Sugiro a versão free desktop.
Ao acessar o link, você irá perceber que existem 4 versões, sendo duas para desktop e duas para servidores. O RStudio Desktop, com o qual trabalharemos, destina-se aqueles que irão atuar individualmente; já os servidores, são para aqueles que trabalharão em equipes e com compartilhamento de informações, ou ainda, para uma empresa com muitos usuários do aplicativo.

As versões pagas possuem mais recursos e suporte. Preste atenção para baixar a solução pretendida (RStudio Desktop).
Atente para escolher a versão para o sistema operacional de seu computador.
Após instalar o R, então instale o RStudio.

Vídeo - Instalando o RStudio.

1.2 RStudio na WEB

Você ainda tem a oportunidade de trabalhar com o RStudio na web. Isso facilita àqueles que não têm uma estação de trabalho fixa e precisam salvar seus arquivos na nuvem, e também, aqueles que tem limitações de desempenho em seus computadores pessoais, ou ainda, aqueles que utilizam um computador do trabalho que tem restrições para instalar programas. 
Fique atento porque a versão free do RStudio Cloud tem limite de tempo para utilização. Portanto, fique logado somente o tempo em que estiver trabalhando, deslogando logo em seguida.

Para acessar o RStudio na nuvem, acesse o link RStudio Cloud, faça seu cadastro e comece a trabalhar.

Vídeo entenda o RStudio Cloud - Entenda o RStudio Cloud

1.3 Conhecendo o RStudio

O RStudio apresenta 4 grandes ambientes:
1. um local onde escreveremos os códigos; 2. um console em que veremos os resultados de nossos códigos; 3. um ambiente no qual podemos ver o estados de nossas variáveis; e 4. um pequeno navegador.

Cada um desses ambientes é dividido em abas com diversas funcionalidades. Para entender melhor, veja o vídeo a seguir.

Vídeo conhecendo o RStudio - Conhecendo o RStudio.

1.4 Pacotes

Pacotes no R são extensões da linguagem que agrupam funções, dados e documentação em um formato padronizado. Eles servem para expandir as capacidades básicas do R, permitindo realizar tarefas específicas como gráficos avançados, análise geoespacial ou bioestatística, sem precisar escrever códigos complexos.
Eles podem ser encontrados em repositórios em diversas partes do mundo, os CRAN que podem ser acessados pela internet normal https://cran.rstudio.org/. No entanto, no RStudio existe um caminho mais fácil, onde você pode acessar o menu Tools, Install Packages e digitar o nome do pacote desejado.
Esses pacotes são baixados e instalados no seu computador em um local específico, a biblioteca (library) onde ficam todos os pacotes. 

Os pacotes contém:
Funções: Códigos prontos para executar ações (ex: ggplot() para gráficos). Documentação: Manuais e arquivos de ajuda que explicam como usar as funções. Dados: Conjuntos de dados de exemplo para prática e testes. Metadados: Arquivos como o DESCRIPTION, que listam a versão, autor e dependências do pacote.
Depois de instalados, eles precisam ser “ligados” ou “chamados” para que funicionem no seu código, por isso, como boa prática, recomendo que logo no início de seu programa você crie um espaço para chama-los. Eles são “chamados” com o comando library(nome_do_pacote).

2 Programação básica

Neste tópico iremos entender os tipos de dados e as operações básicas.

2.1 Editor de texto para programação

No RStudio é possível se editar os programas e salvá-los. O editor do RStudio destaca as palavras reservadas (comandos) , facilitando o seu gerenciamento.
Recomendo que seja definida uma pasta onde devem ser guardados todos os códigos produzidos, isso facilitará a sua recuperação e a manutenção de um histórico de trabalho.

Sempre que for iniciar um código, faça um cabeçalho, indicando quem está escrevendo (no caso, você), a data de criação e alteração, o local, e a finalidade do código. Utilize o comando “#” no início da linha para para que essas informações não sejam entendidas como uma instrução ao computador.

O comentário serve para explicar algo sobre o código e é muito utilizado para a permitir o entendimento da lógica do programador.

# Isto é um comentário. O comentário é utilizado para documentar o código, explicando a lógica e ideias do programador.

2.2 Identificadores

Identificador é o nome pelo qual chamaremos um endereço na memória do computador. Esse endereço pode conter uma variável, uma estrutura de dados com diversos registros ou funções. A seguir vamos entender cada um desses nomes.

Preste bastante atenção: o RStudio é case sensitive, distingue as letras maiúsculas das minúsculas do nome desses identificadores, então, CUIDADO tenha muita atenção na atribuição dos nomes pois a digitação trocada de um caracter pode gerar erro no seu código. Por exemplo: se você digitar x é diferente do que digitar X.

Os identificadores também não podem ser iniciados com números ou **“_”, por exemplo, os identificadores são INVÁLIDOS:**:
1_media_idade
‘_media’

Uma boa prática para quando for necessário identificar a variável com mais de uma palavra é ressaltar essas palavras com a primeira letra maiúscula ou separá-las como , por exemplo:
MediaIdade
- essa notação é chamada de CamelCase; ou
media_idade -
essa notação é chamada de snake_case.

A escolha de bons identificadores é crucial para a legibilidade, manutenibilidade e colaboração em projetos de R. Nomes descritivos e consistentes tornam o código mais fácil de entender não apenas para quem o escreveu (seja semanas ou meses depois), mas também para outros membros da equipe. Identificadores claros reduzem a ambiguidade, minimizam a necessidade de comentários e diminuem a probabilidade de erros de lógica ou de refatoração. Em projetos de longo prazo, a manutenção e a expansão do código são significativamente facilitadas quando as variáveis e funções possuem nomes que refletem claramente seu propósito e conteúdo, aderindo a convenções de estilo (como snake_case ou camelCase).

Vídeo Entendendo os identificadores.

2.3 Tipos de dados

De forma bastante simples, podemos entender uma variável em programação é um espaço de memória onde se armazenam dados para serem utilizados nas instruções (algoritmos).
O R trabalha com os seguintes tipos básicos de dados que podem ser organizados em estruturas de dados como vetores, matrizes, data frames e listas:

  • numéricos - não fazem distinção aparente entre inteiros ou reais, e a notação é em inglês, o “.” (ponto) separa a fração e a “,” (vírgula) separa os decimais.

    • Os tipos de dados numéricos são:

      • int - inteiros - utilizam menos memória e são representados por um ‘L’ após o numeral, ‘5L’, ;

      • dbl - representa números de ponto flutuante, ou números reais. Ocupam mais memória. Exemplo: Atribuindo o valor 5 a uma variável x:
        x <- 5L para inteiro, ou
        y <- 5 para flutuante.

x <- 5L # variável x recebe o numeral 5 inteiro
x
## [1] 5
y <- 5
y 
## [1] 5

Ao criar uma variável o computador cria um endereço capaz de armazenar dados. Esse endereço é o nome da variável, no caso ‘x’ e ‘y’.
Ambas as variáveis armazenam o valor 5, porém ‘x’ por ser inteiro, ocupa menos espaço de memória, enquanto ‘y’ permite cálculos mais precisos.
Essa diferença de espaço de memória é insignificante quando trabalhamos com poucos dados, mas pode ser bastante relevante quando se trabalha com grande quantidade de dados.

  • textos - armazenam valor em letras ou texto.

    • chr - representa vetores de caracteres ou strings
      Exemplo:
      Atribuindo um texto à uma variável a:
      a <- “O RStudio é uma ferramenta poderosa”
a <- "O RStudio é uma ferramenta poderosa." # variável a armazena texto
a
## [1] "O RStudio é uma ferramenta poderosa."
  • lógicos - armazenam verdadeiro (TRUE) ou falso (FALSE). Em R, os valores booleanos TRUE e FALSE são a própria essência do tipo de dado logical. Ou seja, o tipo de dado logical é o que armazena esses valores booleanos.

    • lgl - representa lógico, vetores que contêm apenas TRUE ou FALSE.
      Exemplo:
            # 1. Criar as variáveis
            verdadeiro <- TRUE
            falso <- FALSE
    
            2 # Imprimir 
    ## [1] 2
            print(verdadeiro) # Tipo é logical
    ## [1] TRUE
            print(as.numeric(verdadeiro)) # Converte para numérico
    ## [1] 1
            print(as.numeric(falso))   # Converte para numérico
    ## [1] 0

O R tem uma capacidade de coerção implícita que permite que logical seja tratado como numérico em certas operações: * TRUE é convertido para 1. * FALSE é convertido para 0. Exemplo:

        # 1. Criar as variáveis
        verdadeiro <- TRUE
        falso <- FALSE
        
        # 2. Realizar os cálculos com os valores implícitos das variáveis booleanas
        soma <- verdadeiro + verdadeiro + falso + falso + verdadeiro

        3 # Imprimir o resultado do passo '2'
## [1] 3
        print(soma) # Será apresentado o valor de 'verdadeiros' da sentença aritmética.
## [1] 3
  • datas - existem funções criadas para trabalharem com esse tipo de dados, facilitando muito as operações, em especial as séries temporais e os gráficos. As datas podem ser representadas por dois tipos de dados.

    • date - representa somente datas. Exemplo: Você está programando uma viagem e precisa calcular a duração entre duas datas. Calcule a diferença em dias entre essas duas datas.
        # 1. Criar as variáveis
        data_inicio <- as.Date("2026-01-26")
        data_fim <- as.Date("2026-02-10")

        # 2. Realizar os cálculos com as datas
        diferenca_dias <- data_fim - data_inicio
        
        3 # Imprimir a diferença calculada em '2'
## [1] 3
        print(diferenca_dias)
## Time difference of 15 days
-   dttm - representa datas e horas (uma data + uma hora). É utilizado o pacote **`lubridate`** e que possui o objeto 'POSIXct'.

Exemplo: Em muitas análises financeiras ou de séries temporais, é fundamental manipular datas e horas. Veja como você extrairia o ano, o mês e a hora desse objeto.

        # 1. Criar um objeto POSIXct (data e hora)
        data_hora <- as.POSIXct("2026-01-26 08:15:00", tz = "UTC")
        
        2 # Imprimir a variável 'data_hora'
## [1] 2
        print(data_hora)
## [1] "2026-01-26 08:15:00 UTC"
        # 3. Extrair ano, mês e hora
        ano <- format(data_hora, "%Y")
        mes <- format(data_hora, "%m")
        hora <- format(data_hora, "%H")

        4 # Imprimir os resultados
## [1] 4
        print(ano)
## [1] "2026"
        print(mes)
## [1] "01"
        print(hora)
## [1] "08"
  • fator - é um tipo de dado que o R utiliza para representar as variáveis categóricas, facilitando a criação de gráficos e as análises estatísticas. É utilizado em vetor, por isso, caso você não conheça sobre vetores no R, para melhor compreensão veja o tópico seguinte ‘Vetores’ antes.

    • fctr - é a representação desse tipo de dado. Exemplo: Você possui dados sobre o nível de qualidade de um equipamento, com as categorias “Bom”, “Regular”, “Ruim” que estão armazenados em vetor (pode ser a coluna de um data-frame) com algumas observações (``) e precisa extrair inoformações desse vetor.
            # 1. Criar um vetor com os níveis de qualidade dos equipamentos.
            qualidade_raw <- c("Bom", "Regular", "Bom", "Ruim","Regular","Bom","Bom")
    
            # 2. Definir os níveis em ordem
            niveis_qualidade <- c("Bom", "Regular", "Ruim")  
    
            # 3. Converter para fator com níveis ordenados
            qualidade_fator <- factor(qualidade_raw, levels = niveis_qualidade, ordered = TRUE)
    
            4 # Imprimir resultados
    ## [1] 4
            print(qualidade_fator)
    ## [1] Bom     Regular Bom     Ruim    Regular Bom     Bom    
    ## Levels: Bom < Regular < Ruim
            print(levels(qualidade_fator))
    ## [1] "Bom"     "Regular" "Ruim"

Para formulação de análises e gráficos, é muito útil o comando ‘table’ que faz a contagem dos fatores. Exemplo:

table(qualidade_fator)
## qualidade_fator
##     Bom Regular    Ruim 
##       4       2       1

2.3.1 Vetores

Vetores - podem armazenar números, caracter, boolenos, ou textos - os vetores armazenam apenas dados de um mesmo tipo.

Criando um vetor de números:
vetor <- c(10, 20, 30, 40, 50)

vetor <- c(10, 20, 30, 40, 50) # um vetor contendo 5 números
vetor
## [1] 10 20 30 40 50
# para chamar apenas um dado armazenado no vetor, utilize a notação vetor[posição].
vetor[2] # vai chamar o dado armazenado na segunda posição, no caso, o número 20
## [1] 20

Criando um vetor com nomes:
vetor_a <- c(“aluno”, “idade”, “série”)

vetor_a <- c("aluno", "idade", "série")  # um vetor contendo 3 nomes
vetor_a
## [1] "aluno" "idade" "série"
vetor_a[3] # chamando o dado da terceira posição, no caso a palavra "série"
## [1] "série"

2.3.1.1 Criando um vetor com sequência de dados

1:10 - este comando cria uma sequência de números variando de 1 até 10.
Caso essa sequencia seja adicionada ao uma variável, criaremos um vetor de 10 posições com essa sequência.
x <- 1:10 x <- seq(1:10) - este comando é similar ao de cima, no entanto ele pode ser incrementado com alguns argumento.

x <- seq(from = 1, to = 50, by = 2)

1:10 
##  [1]  1  2  3  4  5  6  7  8  9 10
x <- 1:10
x
##  [1]  1  2  3  4  5  6  7  8  9 10
x <- seq(1:10)
x
##  [1]  1  2  3  4  5  6  7  8  9 10
seq(from = 1, to = 10, by = 2)
## [1] 1 3 5 7 9
seq(from = 5, to = -5, by = -2)
## [1]  5  3  1 -1 -3 -5
seq(from = 1, to = 3, by = 0.2)
##  [1] 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0

Podemos criar repetição de nomes ou números com o comando:
rep(“nome”, 5)

De forma similar, podemos atribuir essa repetição à uma variável, criando um vetor:
x <- rep(“nome”, 5)

rep("nome", 5)  
## [1] "nome" "nome" "nome" "nome" "nome"
x <- rep("nome", 5)  
x[3]
## [1] "nome"
rep(7, 5)  
## [1] 7 7 7 7 7

Podemos criar uma sequência de datas.

# 1. Criando uma variável com o tipo data
data_inicio <- as.Date("2023-01-01")

# 2. Criando a sequência de datas por mês com 24 meses
sequencia_datas_2023 <- seq(from = data_inicio, by = "month", length.out = 24)

3 # Imprimindo a sequencia de dados criada
## [1] 3
print(sequencia_datas_2023)
##  [1] "2023-01-01" "2023-02-01" "2023-03-01" "2023-04-01" "2023-05-01"
##  [6] "2023-06-01" "2023-07-01" "2023-08-01" "2023-09-01" "2023-10-01"
## [11] "2023-11-01" "2023-12-01" "2024-01-01" "2024-02-01" "2024-03-01"
## [16] "2024-04-01" "2024-05-01" "2024-06-01" "2024-07-01" "2024-08-01"
## [21] "2024-09-01" "2024-10-01" "2024-11-01" "2024-12-01"

2.3.2 Matrizes

Matrizes - armazenam matricialmente diversos dados de um mesmo tipo (ou texto, ou número ou booleano).

Vídeo criando vetores e matrizes - Criando vetores e matrizes

Criando uma matriz chamada mat:
mat <- matrix(data = c(10, 20, 30, 40), nrow = 2, ncol = 2)

data = representa os dados que serão inseridos na matriz.
c(10, 20, 30, 40) são os dados, no caso um conjunto de 4 números.
nrow = 2 indica que a matriz terá duas linhas.
ncol = 2 indica que a matriz terá duas colunas.
Como padrão, os dados serão organizados por coluna, ou seja, o preenchimento da matriz será realizado preenchendo-se a 1ª coluna e depois a 2ª coluna.

mat <- matrix(data = c(10, 20, 30, 40), nrow = 2, ncol = 2)   # uma matriz de 2 linhas e 2 colunas de zeros
mat
##      [,1] [,2]
## [1,]   10   30
## [2,]   20   40
# para chamar apenas um dado armazenado na matriz, utilize a notação matriz[linha, coluna]

mat[2,1] # chamará o valor armazenado na segunda linha e primeira coluna, no caso, o valor 20
## [1] 20

Criando uma matriz de texto chamada mat_a:
mat_a <- matrix(data = “aluno”, nrow = 2, ncol = 2)

1
## [1] 1
mat_a <- matrix(data = "aluno", nrow = 2, ncol = 2) # uma matriz de texto com a palavra aluno repetida 4 vezes.
mat_a 
##      [,1]    [,2]   
## [1,] "aluno" "aluno"
## [2,] "aluno" "aluno"
2
## [1] 2
mat_a1 <- matrix(data = c("aluno","classe","professor","teste"), nrow = 2, ncol = 2) # uma matriz de texto com as palavras aluno, classe, professor e teste.

# lembre-se que o preenchimento da matriz se dará por coluna
mat_a1
##      [,1]     [,2]       
## [1,] "aluno"  "professor"
## [2,] "classe" "teste"
mat_a1[2,1] # irá retornar o dado da 2ª linha 1ª coluna, no caso o valor 'classe'.
## [1] "classe"
3
## [1] 3
# para fazer o preenchimento por linha utilize a instrução byrow
mat_a1 <- matrix(data = c("aluno","classe","professor","teste"), nrow = 2, ncol = 2, byrow=TRUE) 
mat_a1
##      [,1]        [,2]    
## [1,] "aluno"     "classe"
## [2,] "professor" "teste"
mat_a1[2,1] # irá retornar o dado da 2ª linha 1ª coluna, no caso o valor 'professor'.
## [1] "professor"

2.3.2.1 Nomes das colunas e linhas da matriz

Podemos atribuir nomes às colunas e linhas de uma matriz

colnames(mat) <- c(“linha1”, “linha2”))
O comando acima atribui os nomes coluna1 e coluna2 para as colunas da matriz.

colnames(mat) <- c("coluna1", "coluna2")

mat
##      coluna1 coluna2
## [1,]      10      30
## [2,]      20      40

rownames(mat) <- c(“linha1”, “linha2”))
O comando acima atribui os nomes linha1 e linha 2 para as linhas da matriz.

rownames(mat) <- c("linha1", "linha2")

mat
##        coluna1 coluna2
## linha1      10      30
## linha2      20      40

Também podemos criar os nomes das coluna diretamente na matriz

dados <- c(10, 12, 11, 13, 8, 9, 10, 13, 12, 18, 17, 19)

# 2. Criando a matriz
matriz <- matrix(dados, 
                 nrow = 3, ncol = 4, byrow = TRUE,
                 dimnames = list(
                            c("Linha A", "Linha B", "Linha C"),
                            c("Coluna1", "Coluna2", "Coluna3", "Coluna4")))
# O nome da linhas é o primeiro vetor da lista; e as colunas o segundo vetor da lista
# Para entender o que é uma lista, veja o proximo tópico, 'Listas'

3 # Imprimindo a matriz
## [1] 3
print(matriz)
##         Coluna1 Coluna2 Coluna3 Coluna4
## Linha A      10      12      11      13
## Linha B       8       9      10      13
## Linha C      12      18      17      19

2.3.2.2 Chamadas de matrizes

As matrizes podem ser acessadas pelo número de suas linhas e colunas.
As matrizes que possuem nomes podem ser chamdas pelos nomes de suas linhas e colunas.

Criando uma matriz para praticar a chamada.

# Criando uma matriz com 3 disciplinas e 5 alunos
# este comando gerará um "warnnig" porque a sequencia 6:9 não é múltiplo de 5 (quantidade de linhas da matriz), mas foi feito propositalmente para haver variação de notas entre os alunos e disciplinas.
notas <- matrix(6:9, nrow = 5, ncol = 3) 

notas
##      [,1] [,2] [,3]
## [1,]    6    7    8
## [2,]    7    8    9
## [3,]    8    9    6
## [4,]    9    6    7
## [5,]    6    7    8
# Atribuindo nomes às colunas e linhas

colnames(notas) <- c("disciplina1", "disciplina2", "disciplina3")
rownames(notas) <- c("aluno1", "aluno2", "aluno3", "aluno4", "aluno5")

notas
##        disciplina1 disciplina2 disciplina3
## aluno1           6           7           8
## aluno2           7           8           9
## aluno3           8           9           6
## aluno4           9           6           7
## aluno5           6           7           8

2.3.2.3 Acessando um dado da matriz.

# Chamando a nota do aluno2, disciplina3. Repare que os nomes aparecem entre aspas dentro dos colchetes.
notas[2,3]
## [1] 9

ou,

notas["aluno2", "disciplina3"]
## [1] 9

2.3.2.4 Acessando uma linha da matriz.

# Chamando todas as notas do aluno3
notas[3,]
## disciplina1 disciplina2 disciplina3 
##           8           9           6

ou,

notas["aluno3",]
## disciplina1 disciplina2 disciplina3 
##           8           9           6

2.3.2.5 Acessando uma coluna da matriz.

# Chamando as colunas, no caso, as notas de uma disciplina
notas[,2]
## aluno1 aluno2 aluno3 aluno4 aluno5 
##      7      8      9      6      7

ou,

notas[,"disciplina2"]
## aluno1 aluno2 aluno3 aluno4 aluno5 
##      7      8      9      6      7

2.3.2.6 Acessando várias linhas e/ou colunas da matriz.

Ainda podemos chamar mais de uma linha (ou coluna) simultâneamente utilizando o intervalo desejado no comando c(incio:fim), no caso de serem sequenciais. Ou ainda, c(linha x, linha y, linha z). Ou ainda, a combinação de ambos: c(incio:fim, linha x).

Acessando as linhas 1 e 2 e a coluna 2

notas[c(1:2), 2]
## aluno1 aluno2 
##      7      8

ou,

notas[c(1:2), "disciplina2"]
## aluno1 aluno2 
##      7      8

Acessando as linhas 1, 2 e 5 e a coluna 2

notas[c(1:2,5), 2]
## aluno1 aluno2 aluno5 
##      7      8      7

ou,

notas[c(1:2,5), "disciplina2"]
## aluno1 aluno2 aluno5 
##      7      8      7

Acessando as linhas 1 e 2 e as colunas 2 e 3.

notas[1:2, c(2:3)]
##        disciplina2 disciplina3
## aluno1           7           8
## aluno2           8           9

2.3.2.7 Realizando operações com linhas ou colunas de uma matriz

Em matrizes numéricas é possível somar suas linas ou colunas.

# 1. Criando a matriz para exemplificar
matriz <- matrix(c(10, 12, 11, 13, 8, 9, 10, 13, 12, 18, 17, 19), 
                 nrow = 3, ncol = 4, byrow = TRUE,
                 dimnames = list(
                            c("Linha A", "Linha B", "Linha C"),
                            c("Coluna1", "Coluna2", "Coluna3", "Coluna4")))

2 # Imprimindo a matriz
## [1] 2
matriz
##         Coluna1 Coluna2 Coluna3 Coluna4
## Linha A      10      12      11      13
## Linha B       8       9      10      13
## Linha C      12      18      17      19
3 # Realizando a soma de linhas
## [1] 3
rowSums(matriz)
## Linha A Linha B Linha C 
##      46      40      66
4 # Realizando a soma de colunas
## [1] 4
colSums(matriz)
## Coluna1 Coluna2 Coluna3 Coluna4 
##      30      39      38      45

2.3.3 Data-frames

Data.frame é uma estrutura de dados similar a matriz. No entanto, cada coluna pode ter um tipo distinto de variável, por exemplo, uma coluna com tipo texto e outra com tipo numérico.

  • uma coluna pode ser chamada de variável (cuidado para não confundir!).
  • uma linha pode ser chamada de registro, observação ou caso.

Vídeo - Criando e manipulando data-frames e listas.

Criando um data.frame chamado df:
df <- data.frame(nome = c(“Adriano”, “José”, “Maria”, “Ana”), idade = c(55, 15, 23, 35))

# um data.frame com duas colunas, a primeira com nomes, e a segunda com idades.
# relembrando: os data.frames são tabelas que armazenam diversos tipos de dados - atenção, uma coluna, também chamada de variável, pode armazenar apenas um tipo de dado.
df <- data.frame(nome = c("Adriano", "José", "Maria", "Ana"), idade = c(55, 15, 23, 35))

df
##      nome idade
## 1 Adriano    55
## 2    José    15
## 3   Maria    23
## 4     Ana    35

Os data.frames, de forma similar às matrizes, podem receber nomes para as colunas e linhas. Os comandos são similares aos das matrizes.

colnames(df) <- c(“NOMES”, “IDADES”)

rownames(df) <- rep(“Aluno”,7)

# Atribuindo nomes às colunas e linhas de um data.frame df
colnames(df) <- c("NOMES", "IDADES")
rownames(df) <- c("Aluno1","Aluno2", "Aluno3", "Aluno4")

df
##          NOMES IDADES
## Aluno1 Adriano     55
## Aluno2    José     15
## Aluno3   Maria     23
## Aluno4     Ana     35

Também, de forma similar à matriz, podemos realizar as chamadas de um data.frame.

df[“Aluno1”,“IDADES”]

df["Aluno1","IDADES"]
## [1] 55

Ou ainda, podemos realizar as chamadas das colunas utilizando o “$”.

df$NOMES
## [1] "Adriano" "José"    "Maria"   "Ana"

Ou ainda, podemos realizar as chamadas das colunas utilizando o “$” e a linha desejada entre colchetes.

df$NOMES[3]
## [1] "Maria"
Resumo Comparativo de Acesso a Colunas no R.
Método Retorno Padrão Uso Principal
df$col Vetor Uso rápido no console e cálculos simples.
df[, "col"] Vetor Programação e seleção dinâmica.
df["col"] Data-frame Quando você precisa manter a estrutura de tabela.
df[[1]] Vetor Extração segura dentro de listas ou loops.

2.3.4 Listas

Lista é um tipo de variável que pode conter diversos tipos de dados, variáveis numéricas, texto, matrizes e df.

Criando uma lista chamada de lista utilizando as variáveis criadas anteriormente: lista <- list(a, x, vetor, vetor_a, mat, mat_a, df)

# Criando uma lista chamada 'lista'
lista <- list(texto = a, 
              vet = vetor, 
              vet_a = vetor_a, 
              mat_num = mat, 
              mat_nom = mat_a, 
              df =df) 
# uma lista armazena diversos tipos de estruturas de dados
# neste caso, a lista armazenou estruturas de dados criadas nos exemplos anteriores, uma variável contendo um nome (a), uma variável contendo um número (x), uma variável contendo um vetor (vetor), uma variável contendo um vetor de nomes (vetor_a), uma matriz (mat), e um data.frame (df)

print(lista)
## $texto
## [1] "O RStudio é uma ferramenta poderosa."
## 
## $vet
## [1] 10 20 30 40 50
## 
## $vet_a
## [1] "aluno" "idade" "série"
## 
## $mat_num
##        coluna1 coluna2
## linha1      10      30
## linha2      20      40
## 
## $mat_nom
##      [,1]    [,2]   
## [1,] "aluno" "aluno"
## [2,] "aluno" "aluno"
## 
## $df
##          NOMES IDADES
## Aluno1 Adriano     55
## Aluno2    José     15
## Aluno3   Maria     23
## Aluno4     Ana     35

2.3.4.1 Chamadas de listas

  1. O Operador de Cifrão ($).

    É a maneira mais amigável. Você digita o nome da lista, coloca o cifrão e o R já te mostra os nomes das “gavetas” nas quais os dados estão armazenados.
1 # Chamando o elemento 'a' da lista criada acima
## [1] 1
print(lista$texto)
## [1] "O RStudio é uma ferramenta poderosa."
2 # Chamando o 'vetor_a' da lista.
## [1] 2
print(lista$vet_a)
## [1] "aluno" "idade" "série"
3 # Chamando o 'df' da lista
## [1] 3
print(lista$df)
##          NOMES IDADES
## Aluno1 Adriano     55
## Aluno2    José     15
## Aluno3   Maria     23
## Aluno4     Ana     35
  1. Colchetes Duplos [[ ]] — dá acesso direto ao conteúdo.

    Imagine que os colchetes simples [ ] selecionam a gaveta inteira (com madeira e tudo), enquanto os colchetes duplos [[ ]] pegam apenas o que está dentro da gaveta. Repare que o nome da ‘gaveta’ vem entre aspas.
1 # chamando o conteúdo de lista$texto
## [1] 1
lista[["texto"]]
## [1] "O RStudio é uma ferramenta poderosa."
2 # Chamando o conteúdo de lista$df - utilizarei o 'print' para melhor visualização
## [1] 2
print(lista[["df"]])
##          NOMES IDADES
## Aluno1 Adriano     55
## Aluno2    José     15
## Aluno3   Maria     23
## Aluno4     Ana     35

Também podemos chamar o conteúdo da ‘gaveta’ pelo seu número sequencial.

1 # chamando o conteúdo de lista$texto
## [1] 1
lista[[1]]
## [1] "O RStudio é uma ferramenta poderosa."

Quando a gaveta tem subdivisões, para chamar o conteúdo de suas subdiviões, utilize dois estágios, primeiro chame a gaveta, e depois chame o seu conteúdo conforme os padrões utilizados para data.frame, matriz, vetor,….

1 # Chamando o dado que está na linha 1 e coluna 2 do df da lista
## [1] 1
lista$df[1,2]
## [1] 55
2 # Chamando a coluna 1 do df da lista - utilizei o print para facilitar a visualização
## [1] 2
print(lista$d[,1])
## [1] "Adriano" "José"    "Maria"   "Ana"

Resumo Visual

Comando O que você está fazendo? Resultado Prático
lista[1] Selecionando uma fatia da lista (a gaveta fechada). Uma nova Lista (menor).
lista[[1]] Abrindo a gaveta e pegando o conteúdo. O objeto original (Vetor, DF, etc).
lista$temp Acessando o conteúdo através do nome. O objeto original (igual ao [[ ]]).

Tabela: Resumo Visual de Acesso a Listas no R
* [[ ]] é usado para extrair um único elemento de uma lista pelo seu nome ou posição, e o resultado é o próprio elemento (sem a estrutura de lista). Por exemplo, minha_lista[[1]] ou minha_lista[["temp"]] retornaria o vetor c(22.5, 23.1, 21.9). * [] (colchete simples) é usado para extrair sub-listas (uma ou mais partes da lista). O resultado é sempre outra lista. Por exemplo, minha_lista[1] retornaria uma lista contendo o vetor temperaturas. * $ é uma forma sintática abreviada de [[ ]] para acessar elementos nomeados, mas não funciona com índices numéricos ou variáveis para o nome.
Portanto, quando se quer extrair o conteúdo real de um elemento da lista (não uma sub-lista) e você sabe o nome ou a posição, [[ ]] é o método mais explícito e robusto. Ele também permite o uso de variáveis para especificar o nome do elemento, o que $ não permite (ex: nome_elemento <- "temp"; minha_lista[[nome_elemento]]).

Dica de Ouro: Se você estiver na dúvida sobre o que tem dentro da lista, use o comando str(lista). Ele mostra a estrutura completa e “desenha” os caminhos para você.

2.4 Comandos básicos

Os comando básicos são utilizados na maioria das atividades de quem trabalha com o RStudio.

2.4.1 Limpando variáveis

O comando para limpar as variáveis é:
rm(VARIÁVEL1, VARIÁVEL2,…)

x <- 3 # Criando a variável x
y <- 5 # Criando a variável y

rm(x,y)
#print(x) # Comando gerará a mensagem: 'Erro: objeto 'x' não encontrado'
#print(y) # Comando gerará a mensagem: 'Erro: objeto 'y' não encontrado'

O comando para limpar todas as variáveis do ambiente é:
rm(list=ls())

Explicação: * ls(): Retorna um vetor de strings com os nomes de todos os objetos no ambiente atual. * rm(list = ...): A função rm() aceita um argumento list que recebe um vetor de nomes de objetos a serem removidos. Ao passar ls() para list, você efetivamente remove todos os objetos listados.

Por que é uma boa prática: Limpar o ambiente antes de iniciar um novo script ou análise é uma boa prática para garantir a reprodutibilidade, evitar conflitos de nomes e gerenciar a memória. * Reprodutibilidade: Garante que o script será executado exatamente da mesma forma em qualquer máquina, sem depender de objetos remanescentes de sessões anteriores que podem não ser recriados. * Evitar Conflitos: Previne que variáveis ou funções com o mesmo nome de sessões anteriores interfiram ou sobrescrevam resultados inesperadamente. * Gerenciamento de Memória: Libera a memória RAM ocupada por objetos grandes e não mais necessários, o que é crucial ao trabalhar com conjuntos de dados extensos ou em ambientes com recursos limitados.
As variáveis podem ser limpas por meio do ícone da vassoura na aba “Enviroument”
Limpando as variáveis


Para limpar a memória utilizada pelo programa utiliza-se o comando:
gc(full = TRUE)

rm(list=ls())

gc(full = TRUE)
##           used (Mb) gc trigger  (Mb) max used  (Mb)
## Ncells 1118167 59.8    2311874 123.5  2311874 123.5
## Vcells 2018835 15.5    8388608  64.0  4353962  33.3

2.4.2 Operações com strings

As variáveis podem receber diversos tipos de dados, mas NÃO É POSSÍVEL FAZER OPERAÇÕES ARITIMÉTICAS COM TEXTO

x <- 2 y <- “O valor de x é:”
z <- x + y - essa operação gerará erro

2.4.2.1 Comandos ‘paste() e paste0()’

O comando paste concatena (junta) as duas variáveis
z <- paste(y, x)
print(z)

Exemplos

Exemplo:

x <- 2
y <- "O valor de x é: "    

paste(y, x)
## [1] "O valor de x é:  2"

Exemplo:

x <- 2
y <- "Posso concatenar números - "    

paste(y, x, " - e textos")
## [1] "Posso concatenar números -  2  - e textos"

O comando paste0() é um comando de concatenação similar ao paste(), no entanto ele não cria espaços entre palavras.

Exemplo:

1 #paste("A","dri","a","no")
## [1] 1
paste("A","dri","a","no")
## [1] "A dri a no"
2 #paste0("A","dri","a","no")
## [1] 2
paste0("A","dri","a","no")
## [1] "Adriano"

O comando cat também imprime na tela, mas ele pode concatenar direto
cat(“O valor de x é:”, x)

Exemplo:

cat("O valor de x é: ", x)  
## O valor de x é:  2

2.4.2.2 Comandos ‘trimws()’, ‘toupper()’, ‘tolower()’ e ‘grep()’

O comando ‘trimws()’ remove os espaços em branco extras do início e do final de uma string.  O comando ‘toupper()’ transforma todas as letras para maiúscula.

        1  # Texto com espaços
## [1] 1
        texto_original <- "  Estatística com R  "
        print(texto_original)
## [1] "  Estatística com R  "
        2  # Remover espaços em branco do início e fim
## [1] 2
        texto_sem_espacos_extras <- trimws(texto_original)
        print(texto_sem_espacos_extras)
## [1] "Estatística com R"
        3  # Transformar para maiúsculas
## [1] 3
        texto_maiusculo <- toupper(texto_sem_espacos_extras)
        print(texto_maiusculo)
## [1] "ESTATÍSTICA COM R"
        4  # Transformar para minúsculas
## [1] 4
        texto_minusculo <- tolower(texto_sem_espacos_extras)
        print(texto_minusculo)
## [1] "estatística com r"

O comando ‘grep()’ localiza um padrão

# 1. Criando um vetor de nomes
frutas <- c("Maçã", "Banana", "Laranja", "Caju", "Graviola")

# 2. Buscar onde aparece o termo "aju"
resultado <- grep(pattern = "aju", x = frutas, ignore.case = TRUE)

3 # O resultado é '[1] 4' - pois "Caju" é o quarto elemento
## [1] 3
print(resultado)
## [1] 4
# 4. Prar retornar o nome que contém o reultado, inclua o parâmetro 'value = TRUE'
resultado <- grep(pattern = "aju", x = frutas, ignore.case = TRUE, value = TRUE)

5 # Imprimindo o novo resultado
## [1] 5
print(resultado)
## [1] "Caju"

2.4.3 Indo para a pasta de trabalho

O comando getwd() verifica o caminho da pasta em que você se encontra.

O comando setwd() permite que você vá para a pasta de trabalho desejada.

setwd(“C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R/Dados/”)

Uma forma de encontrar o caminho de sua pasta de trabalho é copiando o endereço no Windows Explorer. Mas cuidado, nesse caso é necessário mudar as barras invertidas (típicas do Windows) para barras normais.

Utilize novamente o comando getwd() para verificar se você está na pasta desejada.

Outra forma é utilizando a library this_path - path em inglês é “caminho”. Essa biblioteca tem funções que facilitam a organização do trabalho. Veja os exemplos:

Chamando a biblioteca para poder utilizar suas funções:
library(this.path)

Colocando o caminho da pasta atual em uma variável chamada “caminho_atual”:
caminho_atual <- this.dir()

Sugere-se, para trabalhar com base de dados ou arquivos, que se crie uma pasta para os códigos fontes, uma pasta para as bases de dados ou arquivos e, uma pasta para os resultados. Desta forma os arquivos ficam organizados e facilitam o entendimento dos trabalhos e pesquisas.

Atenção! É necessário criar as pastas! Utilize o Windows Explores ou o navegador do próprio RStudio (Files - normalmente no canto inferior direito) para fazer isso. Os comandos abaixo NÃO criam as pastas, somente direcionam guardam os seus endereços.
Caminho para as bases de dados ou arquivos:
caminho_bases <- paste0(path, “/Bases/”)

Observação: o comando paste0() é um comando de concatenação similar ao paste(), que retira os espaços entre palavras. Neste caso, ele serve para evitar erro com espaços desnecessários no caminho.

Caminho para os resultados (arquivos gerados com os resultados) - gráficos, tabelas,…:
caminho_resultados <- paste0(path, “/Resultados/”)

Caminho para guardar os códigos fonte:
caminho_R <- paste0(path, “/R/”)

Observação: para criar uma variável subindo o nível (indo para a pasta de cima) da pasta atual, utilize o comando:

caminho_nivel_acima <- paste(rev(rev(strsplit(caminho_atual, “/”)[[1]])[-1]), collapse = “/”)

O comando acima utiliza as funções paste() de concatena (junta) textos;
A função strsplit() que separa as palavras de um texto - no caso, separa as palavras separadas pela barra “/”; e
A função rev() que inverte a ordem de um vetor - no caso, ela foi utilizada para tirar a última pasta do caminho, invertendo a ordem do vetor, retirando o primeiro campo e depois, voltando à ordem normal.

Exemplos

Para saber em que pasta você está trabalhando, utilize o comando getwd()

getwd()
## [1] "C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R"

Para saber o que tem na pasta em que voce está trabalhando:
dir()

dir() # os resultados foram omitidos. Faça o teste você, no seu computador.

Você pode copiar esse caminho e ajustar a pasta desejada para o seu trabalho.
Para configurar a pasta onde vamos trabalhar, utilize o comando setwd, por exemplo:
setwd(“C:/Users/Documents/R/”)

setwd("~/Adriano/Trabalho/R")

2.4.4 Imprimindo uma informação no console

O comando print imprime no console o que está entre parentesis:
print(“Aluno”)

print("aluno")
## [1] "aluno"
x <- 5
print(x)
## [1] 5

2.4.5 Operadores aritiméticos

Os operadores do R são

  • ” + ” soma
  • ” - ” subtração
  • ” * ” multiplicação
  • ” / ” divisão
  • ” ^ ” exponenciação
  • ” %% ” resto de uma divisão

Exemplos de operações aritiméticas básicas

No R não é preciso declarar a variável
x <- 2 y <- 3

x <- 2
y <- 3

x
## [1] 2
y
## [1] 3

Operadores aritiméticos

x + y
## [1] 5
x - y
## [1] -1

Exemplo:

x * y
## [1] 6

Exemplo:

x / y
## [1] 0.6666667

Exemplo:

x ^ y # ou
## [1] 8
x ** y
## [1] 8

Exemplo:

y %% x # retorna o resto da divisão de 3 por 2, que é 1
## [1] 1

As variáveis numéricas do R se comunicam, isso quer dizer que o R entende número como número e que não precisamos distinguir o que é real e o que é inteiro.

x <- 1.34566932    
y <- 1    
z <- x + y    
z    
## [1] 2.345669

2.4.6 Operações básicas de comparação

  • ” == ” igual
  • ” != ” diferente
  • ” > ” maior
  • ” >= ” maior ou igual
  • ” < ” menor
  • ” <= ” menor ou igual

As operações de comparação retornam os valores TRUE (verdadeiro) ou FALSE (falso)

Exemplos de operações básicas de comparação

x <- 2
y <- 3
z <- 2

x == y # vai retornar FALSE, 2 é diferente de 3
## [1] FALSE

Exemplo:

x != y # vai retornar TRUE, 2 é diferente de 3
## [1] TRUE

Exemplo:

x < y # vai retornar TRUE, 2 é menor do que 3
## [1] TRUE

Exemplo:

x > y # vai retornar FALSE, 2 é menor do que 3
## [1] FALSE

Exemplo:

x >= y # vai retornar FALSE, 2 é menor do que 3
## [1] FALSE

Exemplo:

y >= y # vai retornar TRUE, 2 é igual a 2
## [1] TRUE

Exemplo:

y <= y # vai retornar TRUE, 2 é igual a 2
## [1] TRUE

2.4.7 Leitura do console

Serão apresentados os dois principais comandos, readline(), para leitura de textos e scan(), para leitura de números.

2.4.7.1 Comando readline()

O comando readline() lê uma informação texto da tela do prompt
print(“Digite um valor:”)

x <- readline()

Mas, preste atenção! O readline() lê string, não número. Se for digitado número, o computador entenderá esse número como texto.

print(x)

Exemplo

Execute os comandos no seu computador

print("Digite um valor: ")    
## [1] "Digite um valor: "
x <- readline()   # preste atenção! O readline() lê string, não número    
print(x)          # O retorno é "" porque não houve digitação no console
## [1] ""

2.4.7.2 Comando scan()

Para ler número, utilize a função scan()

cat(“Digite um valor:”)

x <- scan(nmax = 1)

Exemplo

Execute os comandos no seu computador

cat("Digite um valor: ")     
## Digite um valor:
x <- scan(nmax = 1)  

x
## numeric(0)

Como não houve digitação no console, o retorno é ## numeric(0)

2.4.8 Operadores Lógicos

Os operadores lógicos são:

  • ” & ” - e (and)
  • ” | ” - ou (or)
  • ” ! ” - negação

Uma boa forma de entender esses operadores é por meio da Tabela Verdade

tv <- data.frame(Variáveis = c("Verdadeiro", "Verdadeiro", "Verdadeiro", "Verdadeiro", "Falso", "Falso", " ", " "),
                 Operador = c("&","|","&","|","&","|", "!","!"),
                 Variáveis2 = c("Verdadeiro", "Verdadeiro","Falso", "Falso", "Falso","Falso", "Verdadeiro","Falso"), 
                 Resultado = c("Verdadeiro", "Verdadeiro","Falso", "Verdadeiro","Falso","Falso", "Falso", "Verdadeiro") )
tv
##    Variáveis Operador Variáveis2  Resultado
## 1 Verdadeiro        & Verdadeiro Verdadeiro
## 2 Verdadeiro        | Verdadeiro Verdadeiro
## 3 Verdadeiro        &      Falso      Falso
## 4 Verdadeiro        |      Falso Verdadeiro
## 5      Falso        &      Falso      Falso
## 6      Falso        |      Falso      Falso
## 7                   ! Verdadeiro      Falso
## 8                   !      Falso Verdadeiro
TRUE & TRUE
## [1] TRUE
TRUE | TRUE
## [1] TRUE
TRUE & FALSE
## [1] FALSE
TRUE | FALSE
## [1] TRUE
FALSE & FALSE
## [1] FALSE
FALSE | FALSE
## [1] FALSE

2.4.9 Criando números aleatórios

A criação de números aleatórios pode atender diversas distribuições de probabilidade.

Normal:
rnorm(100, mean = 7, sd = 1)
Onde 100 é a quantidade de números gerados;
mean = 7 é a média em torno da qual os números serão criados;
sd = 1 é o desvio padrão a partir do qual os números serão criados.

Uniforme: runif(n = 10, min = 5, max = 20) n = 10 - quantidade de números gerados min = 5 - valor mínimo gerado max = 20 - valor máximo gerado

Binomial: rbinom(quantidade, tamanho, probabilidade)

Exemplos

Exemplo distribuição normal

rnorm(10, mean = 7, sd = 1) 
##  [1] 5.241919 6.584771 4.936091 7.990069 8.421373 8.586769 8.185546 6.957269
##  [9] 8.515414 6.902273
# Plotando o histograma para melhor entendimento
hist(rnorm(n = 1000, mean = 5, sd = 2))

Exemplo distribuição uniforme

runif(n = 10, min = 5, max = 20) # Criando 10 números (n), com valor mínimo de 5 e valor máximo de 20
##  [1] 19.615449 13.463641 16.999099 19.546561 12.669041  5.183327 17.889777
##  [8] 12.590714  5.627079  7.672238
# Plotando o histograma para melhor entendimento
hist(runif(n = 1000, min = 5, max = 20))

Exemplo distribuição binomial

rbinom(10, 50, 0.5) 
##  [1] 26 26 30 20 21 27 32 24 23 24
# Plotando o histograma para melhor entendimento
hist(rbinom(1000, 50, 0.7))

2.4.10 Funções estatísticas básicas


As funções estatísticas básicas são, normalmente, aplicadas à vetores, matrizes, data-frames ou variáveis de uma lista.
Para exemplificar utilizaremos um vetor de x de 1 a 10, uma matriz chamada mat, e um data-frame disponível no R chamado mtcars.
Os dados são:

# Vetor x
x <- 1:10
x
##  [1]  1  2  3  4  5  6  7  8  9 10
# Matriz mat
mat <- matrix(1:25, nrow = 5, ncol = 5)
mat
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    6   11   16   21
## [2,]    2    7   12   17   22
## [3,]    3    8   13   18   23
## [4,]    4    9   14   19   24
## [5,]    5   10   15   20   25
# Data-frame mtcars - apresentando apenas as 3 primeiras linhas
head(mtcars, 3)
##                mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1


As funções estatísticas básicas são:

max(x) identifica o valor máximo de um vetor ou matriz.
Exemplos:

# Maior número do vetor x
max(x)
## [1] 10
# Maior número de mat
max(mat)
## [1] 25
# Maior número da 4 coluna de mat
max(mat[,4])
## [1] 20
# Maior número da terceira linha de mat
max(mat[3,])
## [1] 23
# Maior valor da variável hp no data-frame mtcars
max(mtcars$hp)
## [1] 335


min(x) identifica o menor valor de um vetor ou matriz.
Exemplos:

# Menor número do vetor x
min(x)
## [1] 1
# Menor número de mat
min(mat)
## [1] 1
# Menor número da 4 coluna de mat
min(mat[,4])
## [1] 16
# Menor número da terceira linha de mat
min(mat[3,])
## [1] 3
# Menor valor da variável hp no data-frame mtcars
min(mtcars$hp)
## [1] 52


mean(x) calcula a média dos valores de um vetor ou matriz.
Exemplos:

# Média dos números do vetor x
mean(x)
## [1] 5.5
# Média dos números de mat
mean(mat)
## [1] 13
# Média dos valores da quarta coluna de mat
mean(mat[,4])
## [1] 18
# Média dos números da terceira linha de mat
mean(mat[3,])
## [1] 13
# Média dos valores da variável hp no data-frame mtcars
mean(mtcars$hp)
## [1] 146.6875


median(x) calcula a mediana dos valores de um vetor ou matriz.
Exemplos:

# Mediana dos números do vetor x
median(x)
## [1] 5.5
# Mediana dos números de mat
median(mat)
## [1] 13
# Mediana dos valores da quarta coluna de mat
median(mat[,4])
## [1] 18
# Mediana dos números da terceira linha de mat
median(mat[3,])
## [1] 13
# Mediana dos valores da variável hp no data-frame mtcars
median(mtcars$hp)
## [1] 123


sd(x) identifica o desvio padrão (standart error) dos valores de um vetor ou matriz.
Exemplos:

# Desvio-padrão dos valores do vetor x
sd(x)
## [1] 3.02765
# Desvio-padrão dos valores de mat
sd(mat)
## [1] 7.359801
# Desvio-padrão dos valores da 4 coluna de mat
sd(mat[,4])
## [1] 1.581139
# Desvio-padrão dos valores da terceira lina de mat
sd(mat[3,])
## [1] 7.905694
# Desvio-padrão dos valores da variável hp no data-frame mtcars
sd(mtcars$hp)
## [1] 68.56287


summary(x) calcula um sumários estatístico dos valores de um vetor ou matriz: quartis, média, máximo e mínimo
Exemplos:

# Sumário estatístico dos valores do vetor x
summary(x)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00    3.25    5.50    5.50    7.75   10.00
# Sumário estatístico dos valores de mat
summary(mat)
##        V1          V2           V3           V4           V5    
##  Min.   :1   Min.   : 6   Min.   :11   Min.   :16   Min.   :21  
##  1st Qu.:2   1st Qu.: 7   1st Qu.:12   1st Qu.:17   1st Qu.:22  
##  Median :3   Median : 8   Median :13   Median :18   Median :23  
##  Mean   :3   Mean   : 8   Mean   :13   Mean   :18   Mean   :23  
##  3rd Qu.:4   3rd Qu.: 9   3rd Qu.:14   3rd Qu.:19   3rd Qu.:24  
##  Max.   :5   Max.   :10   Max.   :15   Max.   :20   Max.   :25
# Sumário estatístico dos valores da 4 coluna de mat
summary(mat[,4])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      16      17      18      18      19      20
# Sumário estatístico dos valores da terceira lina de mat
summary(mat[3,])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       3       8      13      13      18      23
# Sumário estatístico dos valores da variável hp no data-frame mtcars
summary(mtcars$hp)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    52.0    96.5   123.0   146.7   180.0   335.0
# Sumário estatístico dos do data-frame mtcars
summary(mtcars)
##       mpg             cyl             disp             hp       
##  Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
##  1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
##  Median :19.20   Median :6.000   Median :196.3   Median :123.0  
##  Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
##  3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
##  Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  
##       drat             wt             qsec             vs        
##  Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  
##  1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  
##  Median :3.695   Median :3.325   Median :17.71   Median :0.0000  
##  Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  
##  3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  
##  Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  
##        am              gear            carb      
##  Min.   :0.0000   Min.   :3.000   Min.   :1.000  
##  1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  
##  Median :0.0000   Median :4.000   Median :2.000  
##  Mean   :0.4062   Mean   :3.688   Mean   :2.812  
##  3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  
##  Max.   :1.0000   Max.   :5.000   Max.   :8.000


hist(x) faz um histograma dos valores de um vetor ou matriz
Exemplos:

# Histograma dos valores da variável hp no data-frame mtcars
hist(mtcars$hp)


Exemplos

Cálculos estatísticos com vetor contendo números que compõem uma distribuição uniforme.

# Distribuição uniforme
y <- runif(10000, min = 0, max = 100)
max(y)
## [1] 99.98645
min(y)
## [1] 0.01376614
mean(y)
## [1] 50.40544
sd(y)
## [1] 28.66591
summary(y)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##  0.01377 25.40420 50.64306 50.40544 75.57060 99.98645
hist(y)


Outro exemplo - cálculos estatísticos com vetor contendo números que compõem uma distribuição normal

# Vetor contendo 10000 elemento compondo uma distribuição normal com média 10 e desvio-padrão 2
y <- rnorm(10000, 10, 2)
max(y)
## [1] 19.36175
min(y)
## [1] 0.8550948
mean(y)
## [1] 9.981969
sd(y)
## [1] 1.993786
hist(y)

summary(y)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.8551  8.6420  9.9660  9.9820 11.3208 19.3617

2.4.11 Arredondamentos

round(número a ser arredondado, quantidade de casas decimais) - arredonda para a quantidade de casas decimais desejada.

round(0.9384,1)
## [1] 0.9
round(0.9499999999,3)
## [1] 0.95

floor(número) - arredonda para o primeiro número inteiro inferior.

floor(0.93)
## [1] 0
floor(8.67)
## [1] 8
floor(-5.84)
## [1] -6

ceiling(número) - arredonda para o primeiro número inteiro superior.

ceiling(10.93)
## [1] 11
ceiling(-5.84)
## [1] -5

trunc(número) - retira as casas decimais do número.

trunc(0.93)
## [1] 0
trunc(10.93)
## [1] 10

2.4.12 Notação científica

O R automaticamente insere a notação científica para números muito grandes. Para forçar que os números não apareçam em notação científica, utilize o comando:
options(scipen = 999)

num <- 1234789012388889999999221
print(num)
## [1] 1.234789e+24
# Aplicando o comando "options(scipen = 999)"
options(scipen = 20)
print(num)
## [1] 1234789012388889965462200

2.5 Comandos de decisão

Os comandos de decisão são aqueles que permitem a escolha do caminho que se pretende seguir para a elaboração de um programa. Em outras palavras, são aqueles que decidem entre situações distintas.
Eles utilizam basicamente os comandos if, else, else if e ifelse. Veja como cada um deles funciona.

Esses comando são utilizados com os operadores de comparação:
- ” == ” igual
- ” != ” diferente
- ” > ” maior
- ” >= ” maior ou igual
- ” < ” menor
- ” <= ” menor ou igual

Eles também podem ser compostos com operadores lógicos:

  • ” & ” - e (and)
  • ” | ” - ou (or)
  • ” ! ” - negação

2.5.1 Comando if

O comando if compara duas variáveis e decide o caminho a tomar considerando o resultado.
Os comandos a serem executados após a decisão devem estar entre chaves ({ }).
Sua estrutura básica é:
Estrutura do if
Veja o exemplo.

x <- 2
y <- 3

if(x < y){
  cat("x é menor do que y e seu valor é:", x, "- o valor de y é: ", y)
}
## x é menor do que y e seu valor é: 2 - o valor de y é:  3


2.5.2 Comando if e else

Quando se deseja incluir um caminho alternativo ao comando if utiliza-se o comando else.
Sua estrutura básica é:
Estrutura do if e else if
Veja o exemplo.

x <- 4
y <- 3

if(x < y){
  cat("x é menor do que y e seu valor é: ", x,"- o valor de y é: ", y)
} else {
  cat("x é maior do que y e seu valor é: ", x ,"- o valor de y é: ", y)
}
## x é maior do que y e seu valor é:  4 - o valor de y é:  3


2.5.3 Comando if e else if

Quando se deseja incluir diversos caminhos alternativos ao comando if, utiliza-se o comando else if. Neste caso, é necessário incluir a condição.
Sua estrutura básica é:
Estrutura do if e else if
Veja o exemplo.

x <- "c"

if(x == "a"){
  cat("x é menor do que zero")
} else if(x == "b"){
  cat("x é maior do que 0")
} else if(x == "0"){
  cat("x é igual a zero")
} else if(x == "0"){
  cat("x não é 'a', nem 'b', nem '0'.")
}

# Sugere-se que o usuário altere os valoes de x e y e veja o comportamento da função.


2.5.4 Comando ifelse

A função ifelse é uma forma mais direta de executar o comando de decisão. Neste caso, não será possível incluir uma sequência de comandos se verdadeiro ou falso, será possível incluir apenas o valor do resultado da comparação.
Sua estrutura básica é:
Estrutura do ifelse
Veja o exemplo:

x <- 4
y <- 3

ifelse(x < y, x ,y)
## [1] 3


2.6 Comandos de repetição

Os comandos de repetição ou loop mais comuns são:
- for
- while
- repeat

Assim como os comandos de decisão, esses comandos são utilizados com os operadores de comparação:
- ” == ” igual
- ” != ” diferente
- ” > ” maior
- ” >= ” maior ou igual
- ” < ” menor
- ” <= ” menor ou igual

Eles também podem ser compostos com operadores lógicos:

  • ” & ” - e (and)
  • ” | ” - ou (or)
  • ” ! ” - negação

Vamos estudar cada um deles.

2.6.1 for

A sintaxe básica do for é:

for ( vetor a ser percorrido ){
sequência de comandos
}

Este comando repete o código entre chaves obedecendo a condição entre parêntesis.
Exemplo:

for(i in 1:5){
  print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5

2.6.2 while

A sintaxe básica do while é:

while(condição){
sequência de comandos
}

“While” significa “enquanto”. Ou seja, os comandos entre chaves serão executados enquanto a condição entre parêntesis for verdadeira.
Atenção: é necessário definir a variável que vai gerar a condição antes de entrar no loop e garantir que essa variável atingirá uma condição diferente de “verdadeiro” durante o loop. Caso isso não ocorra o while entrará em loop infinito e exigirá interrupção forçada por parte do programador.
Exemplo:

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

2.6.3 repeat

O comando “repeat” se diferencia do “while” porque o teste da condição de parada está no fim dos comando, enquanto no comando “while” está no início da sequencia de comandos.
Veja sua sintaxe:

i <- 1 repeat {
sequência de comandos
if (Condição para que a repetição pare) break()
}

De forma similar ao comando “while” é necessário criar uma variável para teste da condição de parada antes do início do loop. E, dentro do loop é necessário assegurar que a condição de parada irá ocorrer, caso contrário o programa entrará em loop contínuo e exigirá ação do programador para forçar a parada.
Veja o exemplo:

i <- 1
repeat{
  print(i)

  i <- i+1
  if(i == 6) break
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5

Atenção: sugere-se manter o incremento de “i” logo acima do teste da condição de parada para evitar dificuldades de interpretação.

2.7 Funções


Video Criando funções
Quando desejamos realizar uma bloco de comandos repetidamente para gerar um resultado específico, criamos uma função. Podemos dizer, a grosso modo que uma função é um programa dentro de um programa principal e é criada para “economizar” linhas de código, padronizar procedimentos, facilitar a escrita e o entendimento do programa.

A sintaxe básica da função é:

identificador = function( argumento1, argumento2, …){

código
código
código

return( argumentos de retorno )
}

Alguns cuidados você deve ter ao criar uma função:

- Identificador - deve obedecer as mesmas regras do identificador das variáveis, ou seja, diferencia as letras maiúsculas e minúsculas, não pode começar com números, deve seguir um padrão que facilite a identificação de sua ação e de que é uma função.

- argumentos - os argumentos podem ser estruturas numéricas, de texto, vetores, matrizes ou data-frames. É importante que esses comandos sejam compreendidos e tenham um padrão para que não ocorram erros nos comandos internos da função. Caso um argumento seja destinado a receber um valor numérico e receba um texto, na execução interno da função ocorrerá um erro. Esse tipo de situação deve ser tratado.

- comandos - seguem os mesmos padrões dos comandos de um programa, com loops, comandos de decisão,….
- return - este comando retorna ao programa de onde é chamada o resultado do processamento executado dentro da função.

2.7.1 Exemplo com criação de funções

Veja o exemplo:

# Criando a função
maior <- function(a, b){
  ifelse( a>b, return(a), return(b))
}

# Chamando a função
a <- 5
b <- 10
c <- 15

maior(a,b)
## [1] 10
maior(c,a)
## [1] 15


# Função com string

nome_completo <- function(primeiro_nome, segundo_nome){
   
  return(cat(primeiro_nome, segundo_nome))  
  
}

nome_completo("Adriano", "Lauro")
## Adriano Lauro

3 Lendo e salvando planilhas texto e Excel

Esta seção permitirá a você ler dados de planilhas ou tabelas para que sejam trabalhados no R.
Existem muitas bases de dados de acesso livre disponíveis para pesquisas e análises que poderão ser acessadas com as instruções abaixo.
Também é possível copiar uma tabela do Excel ou do Word e carrega-la diretamente no RStudio.

3.1 Principais tipos de arquivos

Os mais comuns tipos de dados disponíveis são aqueles organizados em forma de tabelas.
Essas dados podem ser guardados em uma infinidade de formatos, sendo os mais conhecidos “.txt”, “.dat”, “.csv”, “.xls”, “.xlsx”.
O comando básico para a leitura desses dados é o read.table. Desse comando derivam diversos outros como o read.csv, read.csv2,…

Normalmente, quando se lê um arquivo, “jogamos” essas informações em uma variável tipo data-frame, mas existem tipos de dados oriundos de bibliotecas específicas, como por exemplo a tibble que é oriunda do tydverse, ou o rds, xt, ou xts.específicos para séries temporais.

Os principais pacotes para leitura e gravação de arquivos de dados (Planilhas) são, para planilhas no Excel, readxl e openxlsx. Para arquivos txt ou csv, o readr.

library(readr)
library(readxl) 
library(openxlsx)

3.2 Leitura de Dados

O R permite que se leia diversos tipos de dados e os armazene em uma variável. É possível ler formatos de dados oriundos de banco de dados, planilhas, textos, links,… Ele ainda pode se conectar diretamente a um banco de dados.

O read.table é um pacote que pode realizar essas ações e seus parâmetros são:

“file =” - aqui é atribuído o caminho do arquivo no seu computador (também pode ser o caminho da internet).

“sep =” - indica o separador das colunas. As colunas são separadas por ponto e vírgula; por vírgulas; por “|”; ou por espaços “. Para identificar como elas estão separadas, tente abrir o arquivo”.csv”, “.txt”, “.dat” em um editor de textos tipo o notepad, wordpad, notepad++, ou vi, e identifique qual símbolo é utilizado. Outra forma de fazer isso é identificando o formato em um dicionário de dados ou instruções “leiame”, “readme”.

Os arquivos “.xls”, ou “.xlsx” são lidos por pacotes específicos (readxl) e não é necessário a identificação dos separadores. Ao serem abertos por editores de texto apresentarão uma série de símbolos ilegíveis. Portanto, essa técnica de abertura no editor de textos não pode ser utilizada para esses tipos de arquivos.

3.2.1 Lendo dados da web

A principal função para a leitura de dados na web é a read.table.
No entanto, os dados estão armazenados em muitos formatos e as funções disponíveis não são cambiáveis para cada tipo com facilidade.E, frequentemente, os sites são reestruturados e específica.
Os dados abertos do governo, por exemplo, o usuário para acessá-los deve estar logado na conta .gov.
Muitos dados gevernamentais já disponibilizam ferramentas de visualização no próprio site. Tais ferramentas facilitam a visualização por grande parte das pessoas, mas dificultam o acesso dos dados raiz, os chamados microdados, por criarem novos ‘degraus’ para seu acesso.
Por esses motivos, as leituras de dados da web devem ser específicas, considerando todas as características do arquivo e da página.
Uma ação recomendada é, quando a base de dados for necessária para uma pesquisa, que seja baixada, juntamente com os arquivos de metadados, quando existirem, e sejam registrados os dados de acesso.
A leitura direta é recomendada para casos atualizados frequentemente.
O Google Drive e One Drive disponibilizam pacotes para a leiltura de dados em suas bases, inclusive com autenticação. Essa pode ser uma boa solucção para quem quer compartilhar dados, permitindo a autenticação dos usuários.

Os pacotes são:
* Microsoft365R;
install.packages(“Microsoft365R”); e library(Microsoft365R);
* googledrive
install.packages(“googledrive”); e library(googledrive)
* googlesheets4 - para leitura de planilhas do Google install.packages(“googlesheets4”); e library(googlesheets4)

3.2.2 Lendo dados de um arquivo csv ou txt em seu computador

Ao ler o arquivo do computador, fique atento ao endereço onde esse arquivo se encontra, ou seja, a pasta dele.
Existem diversas formas de encontrar esse caminho no seu computador. Uma delas é utilizando o navegador do RStudio, aba “Files” (normalmente, no quadrante inferior esquerdo do RStudio) e encontrar o arquivo desejado. Feito isso, clique na engrenagem e em “Copy Folder Path for Clipboard” e cole esse caminho no argumento “file” da função read.table.

Atenção! Caso esteja utilizando o Windows e copie o endereço do Windows Explorer ou de um navegador, é necessário atentar para as barras. No Windows as barras são invertidas e no R elas devem ser normais, como em um navegador da internet.

DICA!

Você pode utilizar a interface gráfica do RStudio para carregar o arquivo desejado. Acesse o ambiente “File” que, normalmente, fica no canto inferior direito, encontre o seu arquivo e clique sobre ele com o botão esquerdo do mouse. Irá surgir uma caixa com “Import Dataset…”.

Utilizando o navegado do RStudio encontre o seu arquivo.
Utilizando o navegado do RStudio encontre o seu arquivo.

Clique sobre “Import Dataset” e irá surgir a caixa de diálago (abaixo).

Importação do seu arquivo. Observe o caminho da pasta no seu computador onde se encontra o arquivo (1); o cabeçalho e como os dados estão separados (2); e o comando utilizado para a importação de dados (3).
Importação do seu arquivo. Observe o caminho da pasta no seu computador onde se encontra o arquivo (1); o cabeçalho e como os dados estão separados (2); e o comando utilizado para a importação de dados (3).

Observe você tem o caminho da pasta no seu computador onde se encontra o arquivo (1); o cabeçalho e como os dados estão separados (2); e o comando utilizado para a importação de dados (3).

No exemplo acima, as coluna não foram reconhecidas. Nesse caso, altere o campo “Delimeter” para “Semicolon” (ponto e vírgula) e as colunas passarão a ser reconhecidas. Após isso importe o arquivo.

Recomendo que você copie o código de importação e inclua no código que você está elaborando para tornar o processo mais ágil, evitando ter que abrir essa caixa toda vez que for importar o arquivo.

Outro ponto de atenção é quanto ao caminho. Algumas vezes no código apresentado em (3) o caminho surge sem o “~/” inicial - inclua esses caracteres caso o código não funicione. Em (1) o caminho aparece completo, é dessa forma que deve ser chamado no seu comando.

# Lendo o mesmo arquivo no computador - neste caso, utilizei o endereço da internet para baixar o arquivo
library(readr)
qualidade_ar  <- read_delim("~/Adriano/Trabalho/R/dados/airquality.csv", 
    delim = ";", escape_double = FALSE, trim_ws = TRUE)
## Rows: 153 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## dbl (6): Ozone, Solar.R, Wind, Temp, Month, Day
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

3.2.3 Lendo dados de uma planilha Excel

O procedimento é similar ao da leitura de um arquivo .csv, o que muda é o pacote e a função. Observe o exemplo.

# Carregando o pacote
library(readxl)

# Aleitura do arquivo Excel deve utilizar uma outra função, a read_excel

qualidade_ar <- read_excel("~/Adriano/Trabalho/R/dados/airquality.xlsx")

# O comando acima pode ser incrementando incluindo-se o nome da planilha do arquivo Excel, caso exista mais de uma. Neste caso, utilize o comando:

qualidade_ar <- read_excel("~/Adriano/Trabalho/R/dados/airquality.xlsx", sheet = "airquality")

3.2.4 Lendo dados da área de trabalho (clipboard)

Também é possível ler uma tabela de um arquivo Word ou Excel. Para isso basta copiar a tabela (Ctrl + C) e depois chamar o comando:
tabela <- read.table(file = “clipboard”, sep = “, header=TRUE)

Veja o passo-a-passo:

  1. Selecione e copie os dados (no Word ou Excel) que deseja importar para o R (Ctrl + C).

  2. Execute o seguinte código abaixo para importar os dados copiados:
    tabela <- read.table(file = “clipboard”, sep = “, header=TRUE)

Quando copiamos os dados eles ficam armazenados no clipboard (uma memória) do nosso computador, então o R le esses dados em forma de tabela e os coloca na variável desejadas, no caso, “tabela”.

3.3 Salvando os dados

Para salvar os dados em um arquivo no seu computador é possível utilizar os comandos write.table ou write.csv2.

write.table(qualidade_ar, file = “C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R/Dados/qualidade_ar2.csv”, sep = “;”)

Para ver documentação sobre write.table, clique no link.

O pacote writexl possui a função write_xlsx2 utilizada para salvar data-frames em formato planilha Excel, conforme apresentado no exemplo abaixo. Não esqueça de realizar a instalação e o carregamento do pacote antes de tentar utilizar a função.

# Instalando e carregando o pacote
# install.packages("writexl")
library(writexl)

# Salvando em .csv
write.table(qualidade_ar, file = "C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R/dados/qualidade_ar2.csv", sep = ";")    

# Salvando em .txt
write.table(qualidade_ar, file = "C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R/dados/qualidade_ar2.txt", sep = ";")   

# Salvando em .xlsx
write_xlsx(qualidade_ar, "C:/Users/ADRIANO LAURO/OneDrive/Documentos/Adriano/Trabalho/R/dados/qualidade_ar2")

4 Manipulando dados - nativo e dplyr

Existem duas formas de manipulação de dados, a nativa, com comandos básicos do R e a biblioteca dplyr, que faz parte de um conjunto maior de pacotes chamados tydverse (incluí entre outros o ggplot e dplyr).

O dplyr é uma biblioteca muito utilizada que facilita a manipulação dos dados de tabelas. Seus comando tem semelhanças com comandos SQL e com funcionalidades do Excel, o que facilita o entendimento.
A forma de utilização é intuitiva e muitos usuários têm maior facilidade para a compreensão dos seus códigos.

4.1 Bases de dados do R

Para a condução das atividades serão utilizadas as bases de dados do já existentes no R. Para saber quais são essas bases digite “data()” no console.
Ao instalar o pacote tydverse serão incluídas outras bases de dados à esse conjunto.

# Instale e carregue o pacote dplyr
library(dplyr)
## Warning: pacote 'dplyr' foi compilado no R versão 4.4.3
# Conhecendo as bases de dados do R
data()
# A apresentação dos dados foi omitida para não poluir o documento
# Digite esse comando para verificar a variedade de bases disponíveis

Utilizaremos a “storms” por possuir diferentes tipos de dados.
Para visualizar essa base de dados utilize os comandos:

4.1.1 Comandos básicos para visualização dos dados

storms - os primeiros registros (linhas - também chamadas de casos ou observações)

# Digite storms e os dados serão apresentados no console
storms

head(storms, 2) - as 2 primeiras linhas

# Comando apresenta as 2 primeiras linhas
head(storms, 2)
## # A tibble: 2 × 13
##   name   year month   day  hour   lat  long status       category  wind pressure
##   <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>    <int>
## 1 Amy    1975     6    27     0  27.5   -79 tropical de…       NA    25     1013
## 2 Amy    1975     6    27     6  28.5   -79 tropical de…       NA    25     1013
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

tail(storms,2) - visualizara as 6 últimas linhas

# Comando apresenta as 2 últimas linhas
tail(storms, 2)
## # A tibble: 2 × 13
##   name    year month   day  hour   lat  long status      category  wind pressure
##   <chr>  <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>          <dbl> <int>    <int>
## 1 Nicole  2022    11    11    12  33.2 -84.6 tropical d…       NA    25      999
## 2 Nicole  2022    11    11    18  35.4 -83.8 other low         NA    25     1000
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

dim(storms) - as dimensões da tabela (linhas e colunas)

# Comando apresenta o tamanho da base
dim(storms)
## [1] 19537    13

colnames(storms) - visualizará os nomes das colunas

# Comando apresenta o nome das colunas da base
colnames(storms)
##  [1] "name"                         "year"                        
##  [3] "month"                        "day"                         
##  [5] "hour"                         "lat"                         
##  [7] "long"                         "status"                      
##  [9] "category"                     "wind"                        
## [11] "pressure"                     "tropicalstorm_force_diameter"
## [13] "hurricane_force_diameter"
# Comando apresenta o nome das colunas e os seus tipos de dados
glimpse(storms)
## Rows: 19,537
## Columns: 13
## $ name                         <chr> "Amy", "Amy", "Amy", "Amy", "Amy", "Amy",…
## $ year                         <dbl> 1975, 1975, 1975, 1975, 1975, 1975, 1975,…
## $ month                        <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
## $ day                          <int> 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 2…
## $ hour                         <dbl> 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 12, 18,…
## $ lat                          <dbl> 27.5, 28.5, 29.5, 30.5, 31.5, 32.4, 33.3,…
## $ long                         <dbl> -79.0, -79.0, -79.0, -79.0, -78.8, -78.7,…
## $ status                       <fct> tropical depression, tropical depression,…
## $ category                     <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind                         <int> 25, 25, 25, 25, 25, 25, 25, 30, 35, 40, 4…
## $ pressure                     <int> 1013, 1013, 1013, 1013, 1012, 1012, 1011,…
## $ tropicalstorm_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ hurricane_force_diameter     <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…

4.2 Manipulando dados com comandos nativos

O R permite a manipulação e seleção de linhas e colunas na forma nativa, mas a maioria das operações podem ser realizadas por meio dos comandos do pacote dplyr.

Para melhor entendimento, vamos utilizar o data.frame “df” que contém os dados abaixo. Para você criar esse data.frame copie o código abaixo.

df <- data.frame(NOME = c("VENDEDOR 1", "VENDEDOR 2","VENDEDOR 3","VENDEDOR 4","VENDEDOR 5","VENDEDOR 6","VENDEDOR 7"), 
                 Salario_Base = c(1800, 2500, 2500, 3000,3500, 4000, 5000), 
                 Vendas = c(20000,30000,25000,15000,27000,30000,NA))
NOME Salario_Base Vendas
VENDEDOR 1 1800 20000
VENDEDOR 2 2500 30000
VENDEDOR 3 2500 25000
VENDEDOR 4 3000 15000
VENDEDOR 5 3500 27000
VENDEDOR 6 4000 30000
VENDEDOR 7 5000 NA


4.2.1 Acessando os dados

Chamando todo o df:

df[,] # não se preenche o local das linhas e colunas, chama-se todas as linhas ou colunas.
##         NOME Salario_Base Vendas
## 1 VENDEDOR 1         1800  20000
## 2 VENDEDOR 2         2500  30000
## 3 VENDEDOR 3         2500  25000
## 4 VENDEDOR 4         3000  15000
## 5 VENDEDOR 5         3500  27000
## 6 VENDEDOR 6         4000  30000
## 7 VENDEDOR 7         5000     NA

Chamada a linha 2:

df[2,] # preenche-se o espaço das linhas com o número do registro que se quer
##         NOME Salario_Base Vendas
## 2 VENDEDOR 2         2500  30000

Chamada a linhaS 2, 3 e 4:

df[c(2,3,4),] # utiliza-se a função c() contendo os itens ou o intervalo desejado.
##         NOME Salario_Base Vendas
## 2 VENDEDOR 2         2500  30000
## 3 VENDEDOR 3         2500  25000
## 4 VENDEDOR 4         3000  15000
df[c(2:4),] # mesmo resultado do comando acima
##         NOME Salario_Base Vendas
## 2 VENDEDOR 2         2500  30000
## 3 VENDEDOR 3         2500  25000
## 4 VENDEDOR 4         3000  15000

Chamada a coluna 1:

df[,1] # chamando todas as linhas da coluna 1
## [1] "VENDEDOR 1" "VENDEDOR 2" "VENDEDOR 3" "VENDEDOR 4" "VENDEDOR 5"
## [6] "VENDEDOR 6" "VENDEDOR 7"

Chamando a linha 3, coluna 1:

df[3,1] 
## [1] "VENDEDOR 3"

A coluna também pode ser chamada por seu nome:

df$NOME # chamando todas as linhas da coluna cujo nome é "NOME".
## [1] "VENDEDOR 1" "VENDEDOR 2" "VENDEDOR 3" "VENDEDOR 4" "VENDEDOR 5"
## [6] "VENDEDOR 6" "VENDEDOR 7"

Chamando a linha 3 da coluna “NOME”:

df$NOME[3] 
## [1] "VENDEDOR 3"

Chamando as linhas 3, 4 e 5 da coluna “NOME”:

df$NOME[c(3:5)] 
## [1] "VENDEDOR 3" "VENDEDOR 4" "VENDEDOR 5"

Chamando colunas 1 e 2 e todas suas linhas:

df[,c(1,2)] 
##         NOME Salario_Base
## 1 VENDEDOR 1         1800
## 2 VENDEDOR 2         2500
## 3 VENDEDOR 3         2500
## 4 VENDEDOR 4         3000
## 5 VENDEDOR 5         3500
## 6 VENDEDOR 6         4000
## 7 VENDEDOR 7         5000

Chamando colunas 1 e 3, linhas 5:

df[5,c(1,3)] 
##         NOME Vendas
## 5 VENDEDOR 5  27000

4.2.2 Condicional nos comandos básicos

É possível utilizar condições para definição de um subconjunto do data.frame.
Veja o exemplo:
Chamando todas as linhas cujo valor da coluna 2 (salario_base) é menor do que 2900:

df[df$Salario_Base < 2900,]
##         NOME Salario_Base Vendas
## 1 VENDEDOR 1         1800  20000
## 2 VENDEDOR 2         2500  30000
## 3 VENDEDOR 3         2500  25000

No caso acima, a condição de comparação da coluna é colocada na posição da linha.
Outra forma de escrever o mesmo comando:

df[df[,2] < 2900,]
##         NOME Salario_Base Vendas
## 1 VENDEDOR 1         1800  20000
## 2 VENDEDOR 2         2500  30000
## 3 VENDEDOR 3         2500  25000

É possível combinar condições de diversas colunas:

df[df$Salario_Base < 2900 & df$Vendas > 25000,]
##         NOME Salario_Base Vendas
## 2 VENDEDOR 2         2500  30000

É possível chamar dados tipo texto:

df[df$NOME == "VENDEDOR 4",]
##         NOME Salario_Base Vendas
## 4 VENDEDOR 4         3000  15000

4.2.3 Criando linhas

Para se criar uma linha devemos atribuir os valores para cada coluna dessa nova linha:
Veja o exemplo:

df[8,] <- c("Vendedor 8", 1000, 10000) # cuidado 

4.2.4 Atualização de dados

A atualização de dados existentes pode ser feita atribuindo-se o novo valor à posição referenciadas.
Exemplo - atualizando o salário base do vendedor 8:

df[8,2] <- 1920
df[8,]
##         NOME Salario_Base Vendas
## 8 Vendedor 8         1920  10000

Ou:

df$Salario_Base[8] <- 1920
df[8,]
##         NOME Salario_Base Vendas
## 8 Vendedor 8         1920  10000

4.2.5 Criando colunas

df$Perc_comissao <- 5 # todas as linhas dessa nova coluna receberão o valor 5
colnames(df)
## [1] "NOME"          "Salario_Base"  "Vendas"        "Perc_comissao"

É possível criar colunas com valores compostos das demais colunas.
Criaremos uma coluna “Salario” cujo valor é salario_base + (Vendas * Perc_comissao/100).
Veja o exemplo:

# Para fazer essa operação temos que transformar os dados das colunas 2 e 3 que eram de "chr" para numérico. Isso é feito com os comandos abaixo.
df[,2] <- as.numeric((df[,2]))
df[,3] <- as.numeric((df[,3]))

# Agora criamos a nova coluna
df$Salario <- df$Salario_Base + df$Vendas*df$Perc_comissao/100

4.2.6 Unindo linhas - rbind

O comando rbind é utilizado para unir linhas de bases de tabelas distintas. Para sua utilização é fundamental que a quantidade de colunas seja a mesma.
Vamos supor que tenhamos uma outra tabela com mais três vendedores que foram adicionados ao grupo de colaboradores e queremos unir essas tabelas.

Veja essa tabela:

##          NOME Salario_Base Vendas Perc_comissao Salario
## 1  VENDEDOR 8         1800  18000             5    2700
## 2  VENDEDOR 9         2500  20000             5    3500
## 3 VENDEDOR 10         2500  19000             5    3450

O comando para unir as linhas (as tabelas) é rbind(tabela, tabela_nova).
Veja o exemplo.

Veja essa tabela:

rbind(df,df2)
##           NOME Salario_Base Vendas Perc_comissao Salario
## 1   VENDEDOR 1         1800  20000             5    2800
## 2   VENDEDOR 2         2500  30000             5    4000
## 3   VENDEDOR 3         2500  25000             5    3750
## 4   VENDEDOR 4         3000  15000             5    3750
## 5   VENDEDOR 5         3500  27000             5    4850
## 6   VENDEDOR 6         4000  30000             5    5500
## 7   VENDEDOR 7         5000     NA             5      NA
## 8   Vendedor 8         1920  10000             5    2420
## 9   VENDEDOR 8         1800  18000             5    2700
## 10  VENDEDOR 9         2500  20000             5    3500
## 11 VENDEDOR 10         2500  19000             5    3450

4.2.7 Unindo colunas - cbind

O comando cbind() é similar ao rbind(), no entanto ele une as colunas.
Nesse caso é necessário que as colunas tenham a mesma quantidade de linhas.
Vamos supor que queremos adicionar uma coluna com o percentual da comissão dos vendedores, com percentual de 5%.

Veja essa coluna.

# Como o df tem 8 linhas, tenho que criar uma coluna com 8 repetições de 0.05
Percentual_comissao <- rep(0.05,8)

A sintaxe do comando é cbind(tabela, coluna_nova), ou cbind(coluna, coluna_nova).

Veja o exemplo:

cbind(df, Percentual_comissao)
##         NOME Salario_Base Vendas Perc_comissao Salario Percentual_comissao
## 1 VENDEDOR 1         1800  20000             5    2800                0.05
## 2 VENDEDOR 2         2500  30000             5    4000                0.05
## 3 VENDEDOR 3         2500  25000             5    3750                0.05
## 4 VENDEDOR 4         3000  15000             5    3750                0.05
## 5 VENDEDOR 5         3500  27000             5    4850                0.05
## 6 VENDEDOR 6         4000  30000             5    5500                0.05
## 7 VENDEDOR 7         5000     NA             5      NA                0.05
## 8 Vendedor 8         1920  10000             5    2420                0.05

4.2.8 Tratando dados NA

Muitas vezes as bases de dados possuem registros que não possuem dados em determinada coluna. A falta desses dados pode gerar erros em operações e análises estatísticas, por isso é importante saber trata-los.

Existe uma série de comandos para realizar a identificação e tratamento dos NA, “Not Available” (não disponível).

na.omit - remove elementos ‘NA’ do vetor. Repare que no comando abaixo o registro 7 será eliminado.

# Comando remove a linha 7 df porque possui um valor 'NA'
na.omit(df)
##         NOME Salario_Base Vendas Perc_comissao Salario
## 1 VENDEDOR 1         1800  20000             5    2800
## 2 VENDEDOR 2         2500  30000             5    4000
## 3 VENDEDOR 3         2500  25000             5    3750
## 4 VENDEDOR 4         3000  15000             5    3750
## 5 VENDEDOR 5         3500  27000             5    4850
## 6 VENDEDOR 6         4000  30000             5    5500
## 8 Vendedor 8         1920  10000             5    2420

Caso você queira salvar o df sem esse valor, utilize o comando abaixo.

# Comando remove a linha 7 df porque possui um valor 'NA' e carrega em df1
df1 <- na.omit(df)

is.na - retorna um vetor lógico indicando quais os elementos não ‘NA’. Normalmente, esse comando é utilizado em condicionais para identificação e/ou alteração de dados.

is.na(df)
##    NOME Salario_Base Vendas Perc_comissao Salario
## 1 FALSE        FALSE  FALSE         FALSE   FALSE
## 2 FALSE        FALSE  FALSE         FALSE   FALSE
## 3 FALSE        FALSE  FALSE         FALSE   FALSE
## 4 FALSE        FALSE  FALSE         FALSE   FALSE
## 5 FALSE        FALSE  FALSE         FALSE   FALSE
## 6 FALSE        FALSE  FALSE         FALSE   FALSE
## 7 FALSE        FALSE   TRUE         FALSE    TRUE
## 8 FALSE        FALSE  FALSE         FALSE   FALSE

Para substituir um valor ‘NA’ por outro, utilize o comando abaixo. Observe a linha 7.

df[is.na(df)] <- 0
df
##         NOME Salario_Base Vendas Perc_comissao Salario
## 1 VENDEDOR 1         1800  20000             5    2800
## 2 VENDEDOR 2         2500  30000             5    4000
## 3 VENDEDOR 3         2500  25000             5    3750
## 4 VENDEDOR 4         3000  15000             5    3750
## 5 VENDEDOR 5         3500  27000             5    4850
## 6 VENDEDOR 6         4000  30000             5    5500
## 7 VENDEDOR 7         5000      0             5       0
## 8 Vendedor 8         1920  10000             5    2420

4.3 Manipulando dados com o dplyr

O pacote dplyr é um pacote que facilita a manipulação de dados das tabelas.

4.3.1 Carregando o pacote dplyr e outros correlatos

Carregando as bibliotecas necessárias “dplyr”. Portando a instale e depois carregue.
install.packages(“dplyr”)
library(dplyr)

As bibliotecas abaixo são necessárias para o carregamento dos dados:
install.packages(“readr”) - leitura de arquivos
install.packages(“reshape2”) - gráficos
install.packages(“readxl”) - leitura de arquivos formato Excel

Por fim, a biblioteca “stringr” será necessária para manipulação de textos.
install.packages(“stringr”)
library(stringr)

# Depois de instalar, carregue a biblioteca
library(dplyr)
# Outras bibliotecas são utilizadas em conjunto para a manipulação de dados
# Sugiro que carregue todas 
library(stringr)   
library(readr)    
library(reshape2)     
library(readxl) 

4.3.2 Comandos do dplyr

O símbolo “%>%”, chamados de pipe (pronuncia-se paipe) conduz a operação para o comando subsequente

Agora vamos exercitar cada um desses comandos. Para isso, vamos salvar essa base de dados em uma variável. Esse é o procedimento normal quando trabalhamos com cados carregados de uma planilha ou base de dados.

4.3.3 Manipulando dados com dplyr

Utilizaremos a tibble storms, mas os comandos também funcionam para data.frames.

Conhecendo nossa base de dados.

glimpse(storms) # nomes das colunas
## Rows: 19,537
## Columns: 13
## $ name                         <chr> "Amy", "Amy", "Amy", "Amy", "Amy", "Amy",…
## $ year                         <dbl> 1975, 1975, 1975, 1975, 1975, 1975, 1975,…
## $ month                        <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
## $ day                          <int> 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 2…
## $ hour                         <dbl> 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 12, 18,…
## $ lat                          <dbl> 27.5, 28.5, 29.5, 30.5, 31.5, 32.4, 33.3,…
## $ long                         <dbl> -79.0, -79.0, -79.0, -79.0, -78.8, -78.7,…
## $ status                       <fct> tropical depression, tropical depression,…
## $ category                     <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind                         <int> 25, 25, 25, 25, 25, 25, 25, 30, 35, 40, 4…
## $ pressure                     <int> 1013, 1013, 1013, 1013, 1012, 1012, 1011,…
## $ tropicalstorm_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ hurricane_force_diameter     <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…

Além do nome das colunas e quantidade de linhas, esse comando apresenta os tipos de dados de cada coluna.

4.3.4 Select

Para escolher as colunas (variáveis) com que trabalharei, utilizo o select.

# Este comando retorna todas as linhas dessas duas colunas
storms %>% 
  select(name, year) 
## # A tibble: 19,537 × 2
##    name   year
##    <chr> <dbl>
##  1 Amy    1975
##  2 Amy    1975
##  3 Amy    1975
##  4 Amy    1975
##  5 Amy    1975
##  6 Amy    1975
##  7 Amy    1975
##  8 Amy    1975
##  9 Amy    1975
## 10 Amy    1975
## # ℹ 19,527 more rows
# Retorna apenas as 5 primeiras linhas
storms %>% 
  select(name, year) %>% 
  head(5) 
## # A tibble: 5 × 2
##   name   year
##   <chr> <dbl>
## 1 Amy    1975
## 2 Amy    1975
## 3 Amy    1975
## 4 Amy    1975
## 5 Amy    1975

É possível renomear as colunas com o select. Observe que o nome das colunas da variável não mudou, o que mudou foi o nome das colunas selecionadas e retornadas.

# seleciona as 6 últimas linhas da tabela e renomeia como "nome" e "ano"
storms %>% 
  select(nome = name, ano = year) %>% 
  tail(10)
## # A tibble: 10 × 2
##    nome     ano
##    <chr>  <dbl>
##  1 Nicole  2022
##  2 Nicole  2022
##  3 Nicole  2022
##  4 Nicole  2022
##  5 Nicole  2022
##  6 Nicole  2022
##  7 Nicole  2022
##  8 Nicole  2022
##  9 Nicole  2022
## 10 Nicole  2022

É possível criar uma nova tabela a partir da seleção realizada.
Veja o exemplo:

nova_tabela <- storms %>% 
  select(nome = name, ano = year) %>%
  tail(15) 

# Esta nova variável, chamada "nova_tabela" vai conter apenas as 2 colunas (renomeadas) e 6 útlimas linhas selecionadas (tail)
print(nova_tabela)
## # A tibble: 15 × 2
##    nome     ano
##    <chr>  <dbl>
##  1 Nicole  2022
##  2 Nicole  2022
##  3 Nicole  2022
##  4 Nicole  2022
##  5 Nicole  2022
##  6 Nicole  2022
##  7 Nicole  2022
##  8 Nicole  2022
##  9 Nicole  2022
## 10 Nicole  2022
## 11 Nicole  2022
## 12 Nicole  2022
## 13 Nicole  2022
## 14 Nicole  2022
## 15 Nicole  2022

É possível excluir uma coluna, ao invés de selecionar.
Veja o exemplo:

# Vai retornar as 12 colunas da tabela (exceto a coluna "name"), 6 últimas linhas (tail)
storms %>% 
  select(-name) %>% 
  tail(5) 
## # A tibble: 5 × 12
##    year month   day  hour   lat  long status             category  wind pressure
##   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>                 <dbl> <int>    <int>
## 1  2022    11    10    19  29.2 -83   tropical storm           NA    40      989
## 2  2022    11    11     0  30.1 -84   tropical storm           NA    35      992
## 3  2022    11    11     6  31.2 -84.6 tropical depressi…       NA    30      996
## 4  2022    11    11    12  33.2 -84.6 tropical depressi…       NA    25      999
## 5  2022    11    11    18  35.4 -83.8 other low                NA    25     1000
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

Vendo as dimensões do retorno do comando anterior.
Veja o exemplo:

storms %>% 
  select(-name) %>% 
  tail() %>% 
  dim()
## [1]  6 12

É possível retirar várias colunas, para isso utilize a expressão “-c(coluna, coluna, coluna,…)”.
Veja o exemplo.

storms %>% 
  select(-c(lat, long, status, wind, tropicalstorm_force_diameter)) %>% 
  tail
## # A tibble: 6 × 8
##   name    year month   day  hour category pressure hurricane_force_diameter
##   <chr>  <dbl> <dbl> <int> <dbl>    <dbl>    <int>                    <int>
## 1 Nicole  2022    11    10    18       NA      989                        0
## 2 Nicole  2022    11    10    19       NA      989                        0
## 3 Nicole  2022    11    11     0       NA      992                        0
## 4 Nicole  2022    11    11     6       NA      996                        0
## 5 Nicole  2022    11    11    12       NA      999                        0
## 6 Nicole  2022    11    11    18       NA     1000                        0
# Mesmo comando com outra forma de escrever, gerando o mesmo resultado
storms %>% 
  select(-lat, -long, -status, -wind, -tropicalstorm_force_diameter) %>% 
  tail
## # A tibble: 6 × 8
##   name    year month   day  hour category pressure hurricane_force_diameter
##   <chr>  <dbl> <dbl> <int> <dbl>    <dbl>    <int>                    <int>
## 1 Nicole  2022    11    10    18       NA      989                        0
## 2 Nicole  2022    11    10    19       NA      989                        0
## 3 Nicole  2022    11    11     0       NA      992                        0
## 4 Nicole  2022    11    11     6       NA      996                        0
## 5 Nicole  2022    11    11    12       NA      999                        0
## 6 Nicole  2022    11    11    18       NA     1000                        0
storms %>% 
  select(-c(lat, long, status, wind, tropicalstorm_force_diameter)) %>% 
  tail %>% 
  dim
## [1] 6 8

4.3.4.1 Selecionando as colunas numéricas

É possível selecionar colunas com características desejadas como, por exemplo, aquelas que possuem somente dados numérios.

Veja os exemplos:

# Retorna todas as colunas que possuem dados numéricos.
storms %>% 
  select_if(is.numeric) %>% 
  tail
## # A tibble: 6 × 11
##    year month   day  hour   lat  long category  wind pressure
##   <dbl> <dbl> <int> <dbl> <dbl> <dbl>    <dbl> <int>    <int>
## 1  2022    11    10    18  29   -82.8       NA    40      989
## 2  2022    11    10    19  29.2 -83         NA    40      989
## 3  2022    11    11     0  30.1 -84         NA    35      992
## 4  2022    11    11     6  31.2 -84.6       NA    30      996
## 5  2022    11    11    12  33.2 -84.6       NA    25      999
## 6  2022    11    11    18  35.4 -83.8       NA    25     1000
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

4.3.4.2 selecionar apenas as colunas cujo nome começa com uma letra ou texto

É possível selecionar colunas cujo nome comece ou contenha “algumas letras”

# Retorna as colunas que começam com a letra "l".
storms %>% 
  select(starts_with("l")) %>% 
  tail
## # A tibble: 6 × 2
##     lat  long
##   <dbl> <dbl>
## 1  29   -82.8
## 2  29.2 -83  
## 3  30.1 -84  
## 4  31.2 -84.6
## 5  33.2 -84.6
## 6  35.4 -83.8

4.3.4.3 utilizando funções distinct, max, min com select

O comando select pode ser associado com a função distinct. A função “distinct” retorna as linhas únicas de uma determinada coluna.
Veja o exemplo:

# O comando irá apresentar o nome das tempestades registradas
storms %>% 
  select(name) %>% 
  distinct
## # A tibble: 260 × 1
##    name    
##    <chr>   
##  1 Amy     
##  2 Blanche 
##  3 Caroline
##  4 Doris   
##  5 Eloise  
##  6 Faye    
##  7 Gladys  
##  8 Hallie  
##  9 Belle   
## 10 Dottie  
## # ℹ 250 more rows
# O comando irá apresentar o status das tempestades registradas
storms %>% 
  select(status) %>% 
  distinct
## # A tibble: 9 × 1
##   status                
##   <fct>                 
## 1 tropical depression   
## 2 tropical storm        
## 3 extratropical         
## 4 hurricane             
## 5 subtropical storm     
## 6 subtropical depression
## 7 disturbance           
## 8 other low             
## 9 tropical wave
# O comando irá apresentar o minimo da coluna wind
storms %>% 
  select(wind) %>% 
  min
## [1] 10
# O comando irá apresentar o máximo da coluna wind
storms %>% 
  select(wind) %>% 
  max
## [1] 165

4.3.5 arrange

Este comando classifica a tabela de acordo de forma crescente da coluna selecionada.
Veja o exemplo:

# Classificando em ordem crescente
storms %>%
  arrange(wind) %>%
  select(name, wind) %>%
  distinct %>%
  head
## # A tibble: 6 × 2
##   name      wind
##   <chr>    <int>
## 1 Bonnie      10
## 2 Charley     10
## 3 AL031987    10
## 4 Arlene      10
## 5 Bob         10
## 6 Alberto     10
# Classificando em ordem decrescente
storms %>%
  arrange(desc(wind)) %>%
  select(name, wind) %>%
  distinct %>%
  head
## # A tibble: 6 × 2
##   name     wind
##   <chr>   <int>
## 1 Allen     165
## 2 Gilbert   160
## 3 Wilma     160
## 4 Dorian    160
## 5 Allen     155
## 6 Gilbert   155

4.3.6 filter

Esta função filtra AS LINHAS em função do valor da coluna. Ele é similar ao filtro utilizado no Excel. 

# Filtra todas as LINHAS cujo valor na coluna year é maior do que 2015
# Neste caso, o comando retorna as 13 colunas e 1868 linhas com o filtro "year > 2015"
storms %>% 
  filter(year > 2015)
## # A tibble: 4,193 × 13
##    name   year month   day  hour   lat  long status      category  wind pressure
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>          <dbl> <int>    <int>
##  1 Alex   2016     1     7     0  26.6 -75.3 extratropi…       NA    40     1010
##  2 Alex   2016     1     7     6  27.6 -74.7 extratropi…       NA    45     1003
##  3 Alex   2016     1     7    12  28.7 -73.8 extratropi…       NA    50      997
##  4 Alex   2016     1     7    18  30   -72.5 extratropi…       NA    55      987
##  5 Alex   2016     1     8     0  31.4 -70.6 extratropi…       NA    55      986
##  6 Alex   2016     1     8     6  32.4 -68.8 extratropi…       NA    55      986
##  7 Alex   2016     1     8    12  33   -67.1 extratropi…       NA    45      991
##  8 Alex   2016     1     8    18  33.5 -65   extratropi…       NA    45      991
##  9 Alex   2016     1     9     0  34   -62.9 extratropi…       NA    45      991
## 10 Alex   2016     1     9     6  34.5 -60.5 extratropi…       NA    50      991
## # ℹ 4,183 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

É possível utilizar diversos filtros em um único comando. Para isso, separe os filtros com vírgulas. Veja o exemplo:

# Filtra todas as LINHAS cujos valores nas colunas year é igual a 2015, wind é maior do que 50, e pressure menor ou igual a 1000.
# Neste caso, o comando reotrna as 13 colunas e 61 linhas.
storms %>% filter(year == 2015, wind > 50, pressure <= 1000)
## # A tibble: 66 × 13
##    name   year month   day  hour   lat  long status      category  wind pressure
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>          <dbl> <int>    <int>
##  1 Danny  2015     8    20     0  11.7 -42.5 tropical s…       NA    55     1000
##  2 Danny  2015     8    20     6  11.9 -43.5 tropical s…       NA    60      998
##  3 Danny  2015     8    20    12  12.3 -44.4 hurricane          1    65      995
##  4 Danny  2015     8    20    18  12.8 -45.3 hurricane          1    75      990
##  5 Danny  2015     8    21     0  13.2 -46.2 hurricane          2    85      981
##  6 Danny  2015     8    21     6  13.5 -47   hurricane          2    95      973
##  7 Danny  2015     8    21    12  13.8 -47.8 hurricane          3   110      960
##  8 Danny  2015     8    21    18  14.3 -48.6 hurricane          3   105      966
##  9 Danny  2015     8    22     0  14.7 -49.4 hurricane          2    95      973
## 10 Danny  2015     8    22     6  15   -50.3 hurricane          2    85      980
## # ℹ 56 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

Utilize os seguintes operadores para comparação:
==, !=, >, >=, <, <=

É possível compor o comando filter com o select e todos os outros.
Veja o exemplo:

# Utiliza o filtro do exemplo anterior com o comando select
# Neste caso, como o filtro é aplicado em colunas que não estão no select deve vir antes, caso contrário ocorrerá um erro: o filtro não encontrará a coluna, pois ela não foi selecionada.
storms %>% 
   filter(year == 2015, wind > 50, pressure <= 1000) %>% 
   select(name, year, month)
## # A tibble: 66 × 3
##    name   year month
##    <chr> <dbl> <dbl>
##  1 Danny  2015     8
##  2 Danny  2015     8
##  3 Danny  2015     8
##  4 Danny  2015     8
##  5 Danny  2015     8
##  6 Danny  2015     8
##  7 Danny  2015     8
##  8 Danny  2015     8
##  9 Danny  2015     8
## 10 Danny  2015     8
## # ℹ 56 more rows

Observe que as colunas selecionadas podem ser diferentes das que se aplica o filtro.

4.3.6.1 Filtro contendo intervalo de valores

Podemos utilizar a mesma coluna mais de uma vez para definir um intervalo de interesse.
Veja o exemplo:

# A coluna wind com valores maiores que 50 e menores que 70
storms %>% 
  filter(wind > 50, wind < 60)
## # A tibble: 1,106 × 13
##    name      year month   day  hour   lat  long status   category  wind pressure
##    <chr>    <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>       <dbl> <int>    <int>
##  1 Amy       1975     6    30     6  35.6 -70.8 tropica…       NA    55      998
##  2 Amy       1975     7     3     0  37.7 -62.8 tropica…       NA    55      986
##  3 Amy       1975     7     3     6  38.2 -61.2 tropica…       NA    55      986
##  4 Amy       1975     7     3    12  39.3 -59.6 tropica…       NA    55      986
##  5 Caroline  1975     8    31    18  24.8 -98   tropica…       NA    55      993
##  6 Doris     1975     8    30     0  35.3 -48.9 tropica…       NA    55      997
##  7 Doris     1975     8    30     6  35.3 -48.5 tropica…       NA    55      997
##  8 Doris     1975     8    30    12  35.3 -48   tropica…       NA    55      997
##  9 Doris     1975     8    30    18  35   -47.1 tropica…       NA    55      997
## 10 Eloise    1975     9    16    12  19.4 -67.5 tropica…       NA    55     1002
## # ℹ 1,096 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

4.3.6.2 Filtro sobre texto

Quando a coluna tem valores de texto, devemos utilizar esses valores entre aspas.
Veja os exemplos:

# A coluna status cujos valores são de "tropical storm"
storms %>% 
  filter(status != "tropical storm")
## # A tibble: 12,707 × 13
##    name     year month   day  hour   lat  long status    category  wind pressure
##    <chr>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>    <int>
##  1 Amy      1975     6    27     0  27.5 -79   tropical…       NA    25     1013
##  2 Amy      1975     6    27     6  28.5 -79   tropical…       NA    25     1013
##  3 Amy      1975     6    27    12  29.5 -79   tropical…       NA    25     1013
##  4 Amy      1975     6    27    18  30.5 -79   tropical…       NA    25     1013
##  5 Amy      1975     6    28     0  31.5 -78.8 tropical…       NA    25     1012
##  6 Amy      1975     6    28     6  32.4 -78.7 tropical…       NA    25     1012
##  7 Amy      1975     6    28    12  33.3 -78   tropical…       NA    25     1011
##  8 Amy      1975     6    28    18  34   -77   tropical…       NA    30     1006
##  9 Amy      1975     7     4    12  47   -48   extratro…       NA    45      995
## 10 Blanche  1975     7    24     0  26   -68.4 tropical…       NA    20     1014
## # ℹ 12,697 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>
# A coluna status cujos valores são de "tropical storm"
storms %>% 
  filter(status != "tropical storm", status != "hurricane")
## # A tibble: 7,904 × 13
##    name     year month   day  hour   lat  long status    category  wind pressure
##    <chr>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>    <int>
##  1 Amy      1975     6    27     0  27.5 -79   tropical…       NA    25     1013
##  2 Amy      1975     6    27     6  28.5 -79   tropical…       NA    25     1013
##  3 Amy      1975     6    27    12  29.5 -79   tropical…       NA    25     1013
##  4 Amy      1975     6    27    18  30.5 -79   tropical…       NA    25     1013
##  5 Amy      1975     6    28     0  31.5 -78.8 tropical…       NA    25     1012
##  6 Amy      1975     6    28     6  32.4 -78.7 tropical…       NA    25     1012
##  7 Amy      1975     6    28    12  33.3 -78   tropical…       NA    25     1011
##  8 Amy      1975     6    28    18  34   -77   tropical…       NA    30     1006
##  9 Amy      1975     7     4    12  47   -48   extratro…       NA    45      995
## 10 Blanche  1975     7    24     0  26   -68.4 tropical…       NA    20     1014
## # ℹ 7,894 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

Também é possível criar filtros a partir do fragmento de uma expressão ou palavra.Para isso, é necessário utilizar a função string_detect Veja o exemplo:

# A coluna status cujos valores contém o fragamento de palavra "trop"
storms %>% 
  filter(str_detect(status, "trop"))
## # A tibble: 13,110 × 13
##    name   year month   day  hour   lat  long status      category  wind pressure
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>          <dbl> <int>    <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical d…       NA    25     1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical d…       NA    25     1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical d…       NA    25     1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical d…       NA    25     1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical d…       NA    25     1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical d…       NA    25     1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical d…       NA    25     1011
##  8 Amy    1975     6    28    18  34   -77   tropical d…       NA    30     1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical s…       NA    35     1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical s…       NA    40     1002
## # ℹ 13,100 more rows
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

ATENÇÃO! Este comando é CASE SENSITIVE, ou seja, distingue as letras maiúsculas e minúsculas.
Veja o exemplo:

# O mesmo comando anterio com o fragmento "Trop" com o "T" maiúsculo, retorna zero linhas.
storms %>% 
  filter(str_detect(status, "Trop"))
## # A tibble: 0 × 13
## # ℹ 13 variables: name <chr>, year <dbl>, month <dbl>, day <int>, hour <dbl>,
## #   lat <dbl>, long <dbl>, status <fct>, category <dbl>, wind <int>,
## #   pressure <int>, tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>

4.3.6.3 Exemplo combinando select e filter

Podemos combinar os diversos filtros para obter os resultados desejados.
Veja o exemplo:

# Utiliza o filtro do exemplo anterior com o comando select
# Neste caso, como o filtro é aplicado em colunas que não estão no select deve vir antes, caso contrário ocorrerá um erro: o filtro não encontrará a coluna, pois ela não foi selecionada.
storms %>% 
   filter(year == 2015, wind > 50, wind < 1000, str_detect(status, "trop") ) %>% 
   select(name, year, month, starts_with("l"))
## # A tibble: 16 × 5
##    name     year month   lat  long
##    <chr>   <dbl> <dbl> <dbl> <dbl>
##  1 Danny    2015     8  11.7 -42.5
##  2 Danny    2015     8  11.9 -43.5
##  3 Danny    2015     8  15.6 -54  
##  4 Fred     2015     8  14   -20.7
##  5 Fred     2015     9  17.8 -25.7
##  6 Joaquin  2015     9  26   -70.8
##  7 Joaquin  2015     9  25.8 -71.3
##  8 Joaquin  2015    10  41   -47.5
##  9 Joaquin  2015    10  41.5 -43.3
## 10 Kate     2015    11  28   -76.2
## 11 Kate     2015    11  29.5 -75.4
## 12 Kate     2015    11  31.2 -74  
## 13 Kate     2015    11  38.9 -55  
## 14 Kate     2015    11  40   -52  
## 15 Kate     2015    11  41.3 -50.4
## 16 Kate     2015    11  41.9 -49.9

4.3.7 mutate

Este comando alterar colunas existentes ou cria novas colunas que são funções das demais.

Vamos começar com um comando simples, multiplicando o valor da coluna “wind” multiplicando ela por 100.
Veja o exemplo:

# O comando abaixo cria uma 14ª coluna na pesquisa - não muda a variável "storms".
# Apresentadas somente as 6 primeiras linhas - comando head
storms %>%
  mutate(vento = wind * 100) %>%
  head(2)
## # A tibble: 2 × 14
##   name   year month   day  hour   lat  long status       category  wind pressure
##   <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>    <int>
## 1 Amy    1975     6    27     0  27.5   -79 tropical de…       NA    25     1013
## 2 Amy    1975     6    27     6  28.5   -79 tropical de…       NA    25     1013
## # ℹ 3 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, vento <dbl>

Para uma melhor visualização, foram selecionadas apenas 4 colunas:

storms %>%
  mutate(vento = wind * 100) %>%
  select(name, year, wind, vento) %>%
  head(2)
## # A tibble: 2 × 4
##   name   year  wind vento
##   <chr> <dbl> <int> <dbl>
## 1 Amy    1975    25  2500
## 2 Amy    1975    25  2500

Para incluirmos um nome composto na nova coluna, é necessário incluir a aspas para definição desse nome.
No entanto, recomenda-se evitar espaços nos nomes das variáveis. Caso seja necessário incluir um nome composto, una-os com “-” ou “_”: vento_x_100, ou vento-x-100.

storms %>%
  mutate("vento x 100" = wind * 100) %>%
  select(name, year, wind, "vento x 100") %>%
  head(2)
## # A tibble: 2 × 4
##   name   year  wind `vento x 100`
##   <chr> <dbl> <int>         <dbl>
## 1 Amy    1975    25          2500
## 2 Amy    1975    25          2500

4.3.7.1 Alterando um dado específico

Para aleterar um dado específico, é necessário fazer uma seleção e/ou filtro nos dados para evitar alteração indiscriminada na tabela.
Para melhor compreensão dessa operação, em um comando selciono e apresento o dados, e na outra altero o dado.

# Na tempestade Amy vou alterar o dado lat - veja o dado
storms %>%
  select(name, hour, wind, lat) %>%
  filter(name == "Amy",
         hour == 0,
         lat == 27.5)
## # A tibble: 1 × 4
##   name   hour  wind   lat
##   <chr> <dbl> <int> <dbl>
## 1 Amy       0    25  27.5
# Comando para alterar lat para o valor de 30 com mutate
storms %>%
  select(name, hour, wind, lat) %>%
  filter(name == "Amy",
         hour == 0,
         lat == 27.5) %>%
  mutate(lat = 30)
## # A tibble: 1 × 4
##   name   hour  wind   lat
##   <chr> <dbl> <int> <dbl>
## 1 Amy       0    25    30
# Comando para alterar o nome de Amy para AMY com mutate 
storms %>%
  select(name, hour, wind, lat) %>%
  filter(name == "Amy",
         hour == 0,
         lat == 27.5) %>%
  mutate(name = "AAMMYY")
## # A tibble: 1 × 4
##   name    hour  wind   lat
##   <chr>  <dbl> <int> <dbl>
## 1 AAMMYY     0    25  27.5

Atenção! - caso você queira realizar alterações em lote,várias ao mesmo tempo, basta reduzir as restrições do filtro.

# Comando para alterar o nome de Amy para AAMMYY com mutate
storms %>%
  select(name, hour, wind, lat) %>%
  filter(name == "Amy") %>%
  mutate(name = "AAMMYY") %>%
  head(3)
## # A tibble: 3 × 4
##   name    hour  wind   lat
##   <chr>  <dbl> <int> <dbl>
## 1 AAMMYY     0    25  27.5
## 2 AAMMYY     6    25  28.5
## 3 AAMMYY    12    25  29.5

Neste exemplo foram o nome foi alterado nos 31 registros existentes, mas apresentei somente o 3 primeiros para não poluir o documento.

4.3.7.2 Transforndo número em character e vice-versa

Utilize a função as.character para realizar essa transformação.
Utilize a função as.numeric para transformar caracter em número.
Veja os exemplo:

# É criada uma coluna com nome "posicao" e com o formato "chr" 
# em uma nova variável chamada 'stm'
stm <- storms %>% 
  mutate(posicao = as.character(lat)) 

stm %>%
  select(name, lat, posicao) %>%
  head(2)
## # A tibble: 2 × 3
##   name    lat posicao
##   <chr> <dbl> <chr>  
## 1 Amy    27.5 27.5   
## 2 Amy    28.5 28.5
# Transformando a coluna posição de stm em numérico
stm %>% 
  mutate(posicao = as.numeric(posicao)) %>%
  select(name, lat, posicao) %>%
  head(2)
## # A tibble: 2 × 3
##   name    lat posicao
##   <chr> <dbl>   <dbl>
## 1 Amy    27.5    27.5
## 2 Amy    28.5    28.5

Podemos concatenar informações de diversas colunas.

# É criada uma coluna com nome "posicao" e com o formato "chr"
storms %>% 
  mutate(posicao = paste(lat, "-", long)) %>%
  select(name, lat, long, posicao) %>%
  head(2)
## # A tibble: 2 × 4
##   name    lat  long posicao   
##   <chr> <dbl> <dbl> <chr>     
## 1 Amy    27.5   -79 27.5 - -79
## 2 Amy    28.5   -79 28.5 - -79

Podemos criar uma coluna extraindo o primeiro nome de outra coluna.

# É criada uma coluna "com nome "posicao" e com o formato "nome_status" com o primeiro nome da coluna "status"
storms %>% 
  mutate(nome_status = stringr::word(status, 1))%>%
  select(status, nome_status) %>%
  head(2)
## # A tibble: 2 × 2
##   status              nome_status
##   <fct>               <chr>      
## 1 tropical depression tropical   
## 2 tropical depression tropical

4.3.7.3 Trabalhando com datas (em construção)

Utilizae a função lubridate para transformar datas.
Vamos criar uma nova coluna concatenando ano-mês-dia das colunas pré-existentes.
Podemos fazer isso de 2 formas, com a função Date ou utilizando o pacote lubridate.

Para descobrir o formato padrão de datas que seu computador está utilizando, utilize a função Sys.Date().

Veja os exemplos:

# Veirifique o formato de data de seu computador.
Sys.Date()
## [1] "2026-03-26"

Concatene as colunas existentes utilizando a função as.Date().

# Concatenando as coluna existentes com os comandos paste e as.Date 

storms_atualizado <- storms %>%
  mutate(data_completa = as.Date(paste(year, month, day, sep = "-"))) %>%
  select(name, year, month, day, data_completa) %>%
  head(2)
# Utilizando o pacote lubridate
library(lubridate)
## 
## Anexando pacote: 'lubridate'
## Os seguintes objetos são mascarados por 'package:base':
## 
##     date, intersect, setdiff, union
# Criando a coluna 'data_completa'
storms %>%
  mutate(data_completa = make_date(year, month, day)) %>% 
  select(name, year, month, day, data_completa) %>%
  head(2)
## # A tibble: 2 × 5
##   name   year month   day data_completa
##   <chr> <dbl> <dbl> <int> <date>       
## 1 Amy    1975     6    27 1975-06-27   
## 2 Amy    1975     6    27 1975-06-27

4.3.7.4 Criar varias colunas simultaneamente

O comando mutate comporta a criação de várias colunas simultaneamente.
Veja o exemplo:

storms %>% 
  mutate(nome_status = stringr::word(status, 1), posicao = paste(lat, " - ", long), categoria = as.numeric(category))%>%
  select(status, nome_status, lat, long, posicao, category, categoria) %>%
  head
## # A tibble: 6 × 7
##   status              nome_status   lat  long posicao        category categoria
##   <fct>               <chr>       <dbl> <dbl> <chr>             <dbl>     <dbl>
## 1 tropical depression tropical     27.5 -79   27.5  -  -79         NA        NA
## 2 tropical depression tropical     28.5 -79   28.5  -  -79         NA        NA
## 3 tropical depression tropical     29.5 -79   29.5  -  -79         NA        NA
## 4 tropical depression tropical     30.5 -79   30.5  -  -79         NA        NA
## 5 tropical depression tropical     31.5 -78.8 31.5  -  -78.8       NA        NA
## 6 tropical depression tropical     32.4 -78.7 32.4  -  -78.7       NA        NA

4.3.8 group_by

Este comando organiza por grupos - as funções são aplicadas nos grupos e é muito utilizado para elaboração de análises e gráficos. Sua utilidade maior ocorre quando é associado com outros comandos, em especial o summarise.
Aplicado sozinho, ele não retorna no console os seus resultados, por isso não serão apresentados exemplos.

4.3.9 summarise

O comando summarise possibilita a aplicação de funções no cálculo dos valores que retornam de uma consulta. Por isso, normalmente são utilizados com o comando group_by.
Este comando é muito utilizado para análises e confecção de gráficos, como veremos adiante.
Veja os exemplos:

# Nome das tempestades com a média dos valores de wind para cada nome
storms %>%
  group_by(name) %>%
  summarise(mean(wind))
## # A tibble: 260 × 2
##    name     `mean(wind)`
##    <chr>           <dbl>
##  1 AL011993         29.5
##  2 AL012000         25  
##  3 AL021992         29  
##  4 AL021994         24.2
##  5 AL021999         28.8
##  6 AL022000         29.2
##  7 AL022001         25  
##  8 AL022003         30  
##  9 AL022006         31.5
## 10 AL031987         21.2
## # ℹ 250 more rows
# Nome das tempestades com a média dos valores de wind para cada nome
storms %>%
  group_by(name) %>%
  summarise(sd(wind))
## # A tibble: 260 × 2
##    name     `sd(wind)`
##    <chr>         <dbl>
##  1 AL011993       4.16
##  2 AL012000       0   
##  3 AL021992       2.24
##  4 AL021994       5.85
##  5 AL021999       2.5 
##  6 AL022000       1.95
##  7 AL022001       0   
##  8 AL022003       0   
##  9 AL022006       6.58
## 10 AL031987       8.71
## # ℹ 250 more rows
# Nome das tempestades com diversos valores calculados de wind. O "n()" realiza a contagem.
storms %>%
  group_by(name) %>%
  summarise(n(), mean(wind), median(wind), sd(wind), min(wind), max(wind))
## # A tibble: 260 × 7
##    name     `n()` `mean(wind)` `median(wind)` `sd(wind)` `min(wind)` `max(wind)`
##    <chr>    <int>        <dbl>          <dbl>      <dbl>       <int>       <int>
##  1 AL011993    11         29.5             30       4.16          25          35
##  2 AL012000     4         25               25       0             25          25
##  3 AL021992     5         29               30       2.24          25          30
##  4 AL021994     6         24.2             25       5.85          15          30
##  5 AL021999     4         28.8             30       2.5           25          30
##  6 AL022000    12         29.2             30       1.95          25          30
##  7 AL022001     5         25               25       0             25          25
##  8 AL022003     4         30               30       0             30          30
##  9 AL022006    13         31.5             30       6.58          25          45
## 10 AL031987    32         21.2             20       8.71          10          40
## # ℹ 250 more rows
# Status das tempestades com diversos valores calculados de wind. O "n()" realiza a contagem.
storms %>%
  group_by(status) %>%
  summarise(n(), mean(wind), median(wind), sd(wind), min(wind), max(wind))
## # A tibble: 9 × 7
##   status    `n()` `mean(wind)` `median(wind)` `sd(wind)` `min(wind)` `max(wind)`
##   <fct>     <int>        <dbl>          <dbl>      <dbl>       <int>       <int>
## 1 disturba…   171         30.0             30       6.50          20          50
## 2 extratro…  2151         41.5             40      13.5           10         105
## 3 hurricane  4803         86.6             80      20.7           65         165
## 4 other low  1453         25.6             25       6.81          10          80
## 5 subtropi…   151         26.7             30       4.79          10          30
## 6 subtropi…   298         44.4             45       7.89          35          60
## 7 tropical…  3569         27.5             30       3.71          10          30
## 8 tropical…  6830         45.7             45       8.29          35          70
## 9 tropical…   111         28.6             30       4.59          20          40
# Status das tempestades com diversos valores calculados de wind. O "n()" realiza a contagem.
storms %>%
  group_by(status) %>%
  summarise(n(), mean(pressure), median(pressure), sd(pressure), min(pressure), max(pressure))
## # A tibble: 9 × 7
##   status                `n()` `mean(pressure)` `median(pressure)` `sd(pressure)`
##   <fct>                 <int>            <dbl>              <dbl>          <dbl>
## 1 disturbance             171            1009.               1009           3.96
## 2 extratropical          2151             993.                995          14.3 
## 3 hurricane              4803             969.                973          18.7 
## 4 other low              1453            1009.               1009           5.26
## 5 subtropical depressi…   151            1008.               1007           3.45
## 6 subtropical storm       298             998.                998           7.24
## 7 tropical depression    3569            1008.               1008           3.87
## 8 tropical storm         6830             999.               1000           6.92
## 9 tropical wave           111            1009.               1009           1.84
## # ℹ 2 more variables: `min(pressure)` <int>, `max(pressure)` <int>
storms %>%
  filter(lat > 11, lat < 12,  long > -30, long < -25) %>%
  group_by(status) %>%
  summarise(Qtde = n(), media_pressao = mean(pressure), mediana_pressao = median(pressure), dp_pressao = sd(pressure), pressao_min = min(pressure), pressao_max = max(pressure))
## # A tibble: 2 × 7
##   status   Qtde media_pressao mediana_pressao dp_pressao pressao_min pressao_max
##   <fct>   <int>         <dbl>           <int>      <dbl>       <int>       <int>
## 1 tropic…    13         1009.            1008       1.80        1008        1013
## 2 tropic…    15         1002.            1003       4.72         990        1006

5 Gráficos

Existem muitas funções gráficas no R e duas funções muito conhecidas, a função plot e algumas derivadas, como por exemplo a função hist, que utiliza padrões de configuração muito semelhantes; e a função ggplot2 que é muito utilizadas com as funções do dplyr. Para alguns casos a função plot é mais simples e direta. No entanto, conforme aumentamos a complexidade dos dados a serem analisados ou exigimos uma formatação aprimorada, a função ggplot tende a ser melhor.

Existem outras alternativas, mas nos ateremos à essas duas.

Utilizaremos a base de dados disponível no RStudio, dplyr, “storms”, cujas colunas são name, year, month, day, hour, lat, long, status, category, wind, pressure, tropicalstorm_force_diameter, hurricane_force_diameter.

Veja os principais dados:

name Amy Amy
year 1975 1975
month 6 6
day 27 27
hour 0 6
lat 27.5 28.5
long -79 -79
status tropical depression tropical depression
category NA NA
wind 25 25
pressure 1013 1013
tropicalstorm_force_diameter NA NA
hurricane_force_diameter NA NA

No item seguinte abordarei a função plot e em seguida a ggplot. Em ambos os casos serão apresentadas as configurações para se produzir gráficos avançados.

5.1 Função plot e sua configuração

Vamos iniciar com um gráfico bastante simples e acrescentar configurações conforme evoluimos o exemplo. Mas atenção! Algumas configurações são úteis em vários tipos de gráficos, mas outras específicas para um tipo específico.

5.1.1 Scaterplot - gráfico de pontos

x <- 1:10 # atribuo uma sequencia de 1 a 10 ao vetor x
y <- x    # faço o mesmo para y, igualando ao x

plot(x,y)

Conforme queremos personalizar o gráfico, acrescentamos alguns parâmetros.

plot(x, y,
     main = "Título principal",
     sub = "Título secundário",
     xlab = "Nome do eixo x",
     ylab = "Nome do eixo y")

Podemos delimitar os eixos com xlim e ylim. Cuidado! Temos que delimitar o minimo e máximo para cada eixo em um vetor.

plot(x, y,
     main = "Título principal",
     sub = "Título secundário",
     xlab = "Nome do eixo x",
     ylab = "Nome do eixo y",
     xlim = c(1,6),
     ylim = c(3,7))

Para alterar a forma dos pontos utilizamos o pch. Você pode utilizar o *help(“points”)“* ou ?points para pedir uma ajuda ao R.
Com esse argumento você pode também alterar o tipo de ponto.
pch - pode variar de 1 a 25 (cada número representa um tipo). Também pode utilizar ao invés do número uma string, tipo”k”.

Símbolos pch
Símbolos pch
par(mfrow=c(1,2))

plot(x, y,
     sub = "pch = simbolo",
     pch = 16)

plot(x, y,
     sub = "pch = 16",
     pch = "k")

col - altera a cor do ponto.
bg - preenche a cor dos símbolos pch entre 21 e 25.
cex - um vetor numérico para alterar o tamanho do caracter (ou símbolo).
lwd - largura da linha para desenhar símbolos.
Como são muitos argumentos, sugiro que utilize o help(“points”) para ter uma melhor compreensão.

plot(x, y,
     main = "Título principal",
     sub = "Título secundário",
     xlab = "Nome do eixo x",
     ylab = "Nome do eixo y",
     pch = 25,             # tipo de símbolo
     col = "orchid",
     bg = "green",
     cex = 2,
     lwd = 3)

5.1.2 Editando as cores

Podemos aleterar as cores conforme nossas necessidades. O comando colors() permite identificar as 657 cores disponíveis. Aqui, vou apresentar somente as 6 primeiras.

head(colors())
## [1] "white"         "aliceblue"     "antiquewhite"  "antiquewhite1"
## [5] "antiquewhite2" "antiquewhite3"

Incluindo as cores no gráfico.

plot(x, y,
     main = "Título principal",
     sub = "Título secundário",
     xlab = "Nome do eixo x",
     ylab = "Nome do eixo y",
     col = "blue")

data(storms)

plot(storms$pressure, storms$wind,
     xlab = "Pressao", ylab= "Vento",   # Nome dos eixos
     main = "Gráfico de pontos",    # t?tulo do grafico
     xlim = c(870,1025), ylim = c(0,200),  # dimens?o dos eixos
     type = "p",                    # tipo de graficos
     pch = 1,                       # tipo de pontos
     cex = 0.5,                      # tamanho dos pontos
     col = "red",                    # cor dos pontos
     bty = "n",                      # tira bordas do grafico
     axes = FALSE,                       # elimina eixos
) +
  abline(h= mean(storms$wind), col = "red")  + # cria uma llinha horizontal em 0
  abline(v =mean(storms$pressure), col = "blue", lwd = 2, lty = 2)
## integer(0)
# Editando eixos side  o lado 1 para x, 2 para y, 3 para superior.....
axis(side = 1, at=seq(850,1025,25), labels=seq(850,1025,25), cex.axis=0.5)
axis(side = 2, at=seq(0,200,25), labels=seq(0,200,25), cex.axis=0.5) 

OUtro

# 1. Preparação: Criar uma paleta de cores baseada na pressão para dar efeito visual
# Cores mais quentes (vermelho) para pressões baixas (tempestades fortes)
cor_ponto <- colorRampPalette(c("red", "orange", "green"))(100)
cores_mapeadas <- cor_ponto[as.numeric(cut(storms$pressure, breaks = 100))]

# 2. Ajustar parâmetros gráficos (margens e fundo)
par(mar = c(5, 5, 4, 2), bg = "white")

# 3. Criar o gráfico de dispersão
plot(storms$wind, storms$pressure,
     pch = 16,                       # Tipo de ponto (círculo preenchido)
     col = adjustcolor(cores_mapeadas, alpha.f = 0.2), # Transparência para lidar com sobreposição
     cex = 0.8,                      # Tamanho dos pontos
     main = "Correlação: Pressão Central vs. Velocidade do Vento",
     xlab = "Velocidade do Vento (nós)",
     ylab = "Pressão Central (mbar)",
     cex.axis = 0.8,                 # Reduz o tamanha dos números dos eixos
     las = 1,                        # Eixo Y na horizontal
     frame.plot = FALSE)             # Remove a caixa completa do gráfico

# 4. Adicionar grade para facilitar a leitura técnica
grid(col = "lightgray", lty = "dotted")

# 5. Adicionar legenda para as cores
legend("topright", 
       legend = c("Alta Pressão (Fraco)", "Média Pressão", "Baixa Pressão (Forte)"),
       col = c("green", "orange", "red"),
       pch = c(16, 16, 16),
       lty = c(NA, NA, NA),
       lwd = c(NA, NA, NA),
       bty = "n",
       cex = 0.8)

5.1.3 Histograma

O histograma é uma ferramenta de visualização gráfica que representa a distribuição de frequências de uma variável quantitativa (numérica).

Diferente de um gráfico de barras convencional — que lida com categorias — o histograma lida com intervalos numéricos. Ele agrupa os dados em colunas adjacentes, onde a base de cada coluna representa um intervalo de valores e a altura representa a quantidade de dados (frequência) presentes naquele intervalo.

O histograma é muito importante para a análise visual dos dados na análise exploratória. Com ele conseguimos:

  • Identificar a tendência central: Onde a maioria dos dados se concentra.

  • Visualizar a dispersão: O quão espalhados os dados estão.

  • Detectar assimetria: verificar se os dados pendem mais para a direita (positiva) ou esquerda (negativa).

    A construção segue três passos principais:

  • Definição dos Bins (Classes): O intervalo total dos dados (máximo - mínimo) é dividido em subintervalos de mesma largura.

  • Contagem de Frequência: conta-se quantos pontos de dados caem dentro de cada “bin”.

  • Desenho das Barras: As barras são desenhadas sem espaços entre si, indicando a continuidade da variável.

    A largura de cada coluna (\(h\)) é calculada dividindo a amplitude total dos dados pelo número de classes (\(k\)) desejado:\[h = \frac{\text{Valor Máximo} - \text{Valor Mínimo}}{k}\].


Escolher o número de classes (\(k\)) não é algo óbvio, estatísticos criaram fórmulas para automatizar isso. No R, a função hist() utiliza por padrão a Regra de Sturges.
Regra de Sturges (Padrão no R) - É ideal para dados com distribuição normal e amostras de tamanho moderado.
\[k = 1 + \log_2(n)\]

(Onde \(n\) é o número total de observações).

Regra de Scott - melhor para amostras maiores, pois leva em conta o desvio padrão
(\(\sigma\)).\[h = \frac{3.5 \times \sigma}{\sqrt[3]{n}}\]

Regra de Freedman-Diaconis - É a mais robusta para dados com outliers, pois utiliza o Intervalo Interquartil (\(IQR\)) em vez do desvio padrão.
\[h = 2 \times \frac{IQR}{\sqrt[3]{n}}\]
Ao olhar para um histograma, atente-se ao formato da curva invisível que ele desenha:
- Simétrico: a maior parte dos dados está no centro, diminuindo gradualmente para as pontas.
- Assimétrico à Direita (positivo): a “cauda” do gráfico é mais longa no lado direito (valores altos).
- Assimétrico à Esquerda (negativo): a “cauda” do gráfico é mais longa no lado esquerdo (valores baixos).
- Bimodal ou Multimodal: o gráfico apresenta dois ou mais “picos”, sugerindo que sua amostra pode ter dois ou mais grupos distintos.

Produzindo um Histograma no R com hist() A função nativa do R para gerar histogramas é a hist(). Vamos usar a variável wind da base storms como exemplo:

hist(storms$wind)

Tentando delinear o número de intervalos.

hist(storms$wind, breaks = 10) # Sugere 15 intervalos

Aprimorando a configuração.

# Configuração otimizada do Histograma
hist(storms$wind, 
     breaks = 20,                   # Aumenta o detalhamento (bins)
     main = "Distribuição da Velocidade dos Ventos", 
     sub = "Dados da base 'storms' (dplyr)",
     xlab = "Velocidade do Vento (nós)", 
     ylab = "Frequência Absoluta",
     col = "#56B4E9",               # Uma cor azul profissional (colorblind friendly)
     border = "white",              # Melhora a separação visual das barras
     xlim = c(0, 160),              # Define o limite do eixo X para cobrir toda a amplitude
     las = 1,                       # Rotaciona os números do eixo Y para a horizontal
     prob = FALSE)                  # FALSE para frequência absoluta, TRUE para densidade

5.1.4 Boxplot

O boxplot (ou diagrama de caixa) é uma ferramenta estatística poderosa para visualizar a distribuição e a variabilidade de um conjunto de dados. Ele é especialmente útil porque resume, em um único gráfico, cinco números importantes e ainda identifica visualmente os valores atípicos (outliers).
Para entender um boxplot, imagine que ele divide seus dados em quatro partes iguais (quartis):
A Caixa (Box): Representa os 50% centrais dos seus dados e é representadas por:
* Borda Inferior: é o 1º Quartil (Q1) (25% dos dados estão abaixo deste ponto).
* Linha Central: é a Mediana (o valor exato que divide os dados ao meio).
* Borda Superior: é o 3º Quartil (Q3) (75% dos dados estão abaixo deste ponto).
Hastes (Whiskers): são as linhas que saem da caixa. Elas se estendem até o valor mais alto e o mais baixo que não sejam considerados outliers.
Pontos Isolados (Outliers): Valores que estão muito longe do restante dos dados. No R, por padrão, são valores que ultrapassam \(1.5 \times\) o tamanho da caixa (\(IQR\)).

O boxplot oferece as seguintes análises:
- simetria: Se a linha da mediana estiver no centro da caixa, os dados são simétricos. Se estiver perto do topo ou fundo, os dados são assimétricos (skewed).
- Dispersão: uma caixa “comprida” indica que os dados variam muito. Uma caixa “achatada” indica que os valores estão muito próximos. - Comparação entre grupos: é excelente forma de comparar visulamente os dados de diferentes grupos, por exemplo, a pressão das tempestades entre diferentes meses. Você consegue ver rapidamente qual mês tem a maior variação e onde ocorrem os eventos mais extremos.

boxplot(storms$wind)

boxplot(wind ~ month, data = storms,
        col = "skyblue",
        main = "Velocidade dos Ventos por Mês",
        xlab = "Mês",
        ylab = "Vento (nós)")

# 1. Cálculos Estatísticos
vento <- storms$wind
media   <- mean(vento, na.rm = TRUE)
mediana <- median(vento, na.rm = TRUE)

# 2. Configurações de layout
par(mar = c(5, 5, 4, 2))

# 3. Criar o Boxplot
b <- boxplot(vento, 
        horizontal = TRUE,           # Gráfico na horizontal para facilitar leitura
        col = "#E6E6FA",             # Lavender (mesmo padrão do histograma)
        border = "black",            # Cor das linhas da caixa
        main = "Boxplot da Velocidade dos Ventos",
        xlab = "Vento (nós)",
        notch = TRUE,                # Adiciona um entalhe na mediana (intervalo de confiança)
        outline = TRUE,              # Exibe os outliers (pontos pretos)
        frame = FALSE)               # Remove o quadro externo

# 4. Adicionar Linhas Verticais para Média, Mediana e Moda
# (As linhas cruzam o gráfico para facilitar a comparação visual)
abline(v = media,   col = "red",       lwd = 2, lty = 2) # Média
abline(v = mediana, col = "blue",      lwd = 2, lty = 4) # Mediana
# Nota: A moda no boxplot coincide com a linha da maior concentração de dados

# 5. Adicionar Grade Vertical
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted")

# 6. Adicionar Legenda Detalhada
legend("topright", 
       legend = c(paste("Média:", round(media, 1)), 
                  paste("Mediana:", mediana),
                  "Outliers (Pontos)"),
       col = c("red", "blue", "black"),
       lty = c(2, 4, NA),
       pch = c(NA, NA, 1),           # Símbolo do ponto para outliers
       lwd = c(2, 2, NA),
       bty = "n",
       cex = 0.9)

# 7. Adicionar rótulos numéricos nos quartis (opcional)
stats <- boxplot.stats(vento)$stats
text(x = stats, y = 1.3, labels = stats, col = "darkblue", font = 2, cex = 0.8)

Boxplot por categoria

# 1. Preparação: Garantir que 'category' seja um fator ordenado
# Isso evita que o gráfico exiba as categorias fora de ordem (ex: 1, 10, 2)
storms$category <- as.factor(storms$category)

# 2. Configurações de layout e margens
par(mar = c(5, 5, 4, 2))

# 3. Criar o Boxplot comparativo
boxplot(wind ~ category, 
        data = storms,
        main = "Intensidade do Vento por Categoria de Tempestade",
        xlab = "Categoria da Tempestade",
        ylab = "Vento (nós)",
        col = terrain.colors(length(unique(storms$category))), # Cores graduais
        border = "black",
        las = 1)                 # Números do eixo Y na horizontal

# 4. Adicionar grade horizontal para facilitar a leitura dos níveis de vento
grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

Detalhes técnicos desta visualização:

  • wind ~ category: Esta fórmula diz ao R: “Analise a variável numérica wind dividida pelos grupos da variável categórica category”.

  • terrain.colors(): Utilizei uma paleta que gera um degradê de cores, o que ajuda a enfatizar visualmente a progressão da gravidade das categorias.

  • Outliers por Categoria: Note que em cada categoria existem pontos (outliers). Isso mostra que, embora uma tempestade seja classificada como “Categoria 1”, ela pode ter picos de vento que fogem da média daquela classe específica.

  • Ajuste de Eixos: Se houver categorias com nomes longos, você pode usar las = 2 no comando boxplot para girar os nomes das categorias no eixo X.

5.1.5 Gráfico violino

Para criar um gráfico de violino é necessário utilizar o pacote vioplot, pois o R nativo não possui uma função violin() pré-instalada.

O gráfico de violino combina as vantagens do boxplot com um histograma espelhado (densidade), sendo ideal para visualizar a “massa” dos dados de vento da base storms.

# 1. Instalar e carregar o pacote necessário
if(!require(vioplot)) install.packages("vioplot")
library(vioplot)

# 2. Configurar o ambiente gráfico
par(mar = c(5, 5, 4, 2), bg = "#F9F9F9")

# 3. Criar o gráfico de violino detalhado
vioplot(storms$wind, 
        names = "Velocidade do Vento",
        col = "lightblue",          # Cor do corpo do violino
        border = "steelblue",       # Cor da borda
        rectCol = "darkblue",       # Cor do boxplot interno
        lineCol = "red",            # Cor das linhas internas
        colMed = "white",           # Cor do ponto da mediana
        areaEqual = FALSE,          # Mantém a escala de densidade original
        main = "Distribuição de Ventos (Gráfico de Violino)",
        ylab = "Vento (nós)",
        las = 1)

# 4. Adicionar Linha da Média (Customização Extra)
media_wind <- mean(storms$wind, na.rm = TRUE)
abline(h = media_wind, col = "red", lty = 2, lwd = 2)

# 5. Adicionar anotação de texto para a Média
text(x = 1.3, y = media_wind + 5, 
     labels = paste("Média:", round(media_wind, 1)), 
     col = "red", font = 2)

# 6. Adicionar grade para facilitar a leitura técnica
grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

# 7. Legenda explicativa
legend("topright", 
       legend = c("Mediana (Ponto Branco)", "Média (Linha Tracejada)", "IQR (Retângulo Azul)"),
       col = c("darkblue", "red", "darkblue"),
       lty = c(NA, 2, 1),
       pch = c(16, NA, NA),
       bty = "n", 
       cex = 0.8)

Detalhes técnicos desta visualização:

  • Corpo do Violino: A largura do “violino” representa a densidade de probabilidade. Onde o gráfico é mais largo, há mais registros daquela velocidade de vento na base storms.

  • Boxplot Interno: O vioplot desenha automaticamente um boxplot simplificado dentro do violino (o retângulo azul escuro representa o Intervalo Interquartil).

  • colMed = "white": Destaca a mediana como um ponto branco central, facilitando a localização rápida do centro dos dados.

  • rectCol e lineCol: Permitem separar visualmente as partes do gráfico, tornando-o profissional e pronto para apresentações acadêmicas ou relatórios de 2026.

  • Vantagem sobre o Boxplot: Enquanto o boxplot esconde a distribuição (se é bimodal ou unimodal), o violino mostra claramente que a maioria das tempestades em storms se concentra em velocidades baixas (perto de 30-50 nós).

Gráfico de Violino por categoria

# 1. Carregar pacote
if(!require(vioplot)) install.packages("vioplot")
library(vioplot)

# 2. Preparação: Converter status para fator para garantir a organização
storms$status <- as.factor(storms$status)

# 3. Ajustar margens (Aumentamos a margem inferior 'mar[1]' para os nomes caberem)
par(mar = c(10, 5, 4, 2)) 

# 4. Criar o gráfico de violino por Status
vioplot(wind ~ status, 
        data = storms,
        col = rainbow(length(levels(storms$status)), s = 0.5), # Cores distintas para cada status
        border = "darkgray",
        rectCol = "black",        # Boxplot interno em preto
        colMed = "white",         # Mediana em destaque branco
        main = "Variabilidade do Vento por Status da Tempestade",
        ylab = "Vento (nós)",
        xlab = "",                 # Removemos o rótulo do eixo X para não sobrepor
        las = 2,                   # Rotaciona os nomes do Status em 90 graus
        cex.names = 0.8)           # Ajusta tamanho da fonte dos nomes

# 5. Adicionar grade horizontal de referência
grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

# 6. Adicionar título ao eixo X manualmente (posicionado abaixo dos nomes rotacionados)
mtext("Status da Tempestade", side = 1, line = 8, font = 2)

# 7. Adicionar legenda informativa
legend("topright", 
       legend = c("Mediana", "Distribuição (Densidade)", "Quartis (Boxplot)"),
       pch = c(16, NA, 15), 
       col = c("white", "gray", "black"),
       bty = "n", 
       cex = 0.8)

Detalhes técnicos desta visualização:

  1. Assimetria (Symmetry): Observe como as categorias mais baixas (0 e 1) têm violinos “gordos” na base, indicando que a maioria das tempestades nessas classes fica no limite inferior de velocidade.

  2. Multimodalidade: Se um violino tiver dois “ombros” largos, isso sugere que existem dois grupos distintos de intensidades dentro da mesma categoria.

  3. Comparação de Medianas: O ponto amarelo permite comparar rapidamente se o salto de velocidade entre a Categoria 3 e 4 é maior do que entre a 1 e 2.

  4. Cores (Terrain Colors): A paleta facilita a visualização da progressão: tempestades mais fracas em tons de verde/marrom e as mais fortes (categorias 4 e 5) em tons mais claros/amarelados.

Este formato é ideal para relatórios técnicos em 2026, pois apresenta a estatística descritiva (boxplot interno) e a distribuição probabilística (curva de densidade externa) simultaneamente.

5.1.6 Gráfico de pizza

Gráficos de pizza são recomendados quando existem poucas categorias, caso contrário ele pode se tornar de difícil interpretação. Quando existem muitas categorias recomenda-se a utilização do gráfico de barras, conforme próximo exemplo.

Para criar o gráfico de pizza temos que colocar os nomes e valores em colunas e para isso utiliza-se a função table como auxiliar. Veja o exemplo:

# Funcao table organiza os dados, contando quantos registros de status
# existem para cada tipo de status. Ela é útil quando o tipo de dado
# da coluna é um "factor"

# 1. Preparação dos dados: contar frequências
status_freq <- table(storms$category)
kable(status_freq)
Var1 Freq
1 2548
2 993
3 593
4 553
5 116
# 2. Criar porcentagens para exibir no gráfico
porcentagens <- round(100 * status_freq / sum(status_freq), 1)
labels_custom <- paste(names(status_freq), "-", porcentagens, "%")

# 3. Definir uma paleta de cores variada
cores <- rainbow(length(status_freq), s = 0.6, v = 0.9)

# 4. Ajustar margens para garantir que a legenda caiba
par(mar = c(1, 1, 3, 1))

# 5. Criar o gráfico de pizza
pie(status_freq, 
    labels = NA,               # Remove labels automáticos para usar legenda externa
    main = "Proporção de Status das Tempestades", 
    col = cores, 
    border = "white",          # Bordas brancas entre fatias para melhor contraste
    clockwise = TRUE,          # Organiza no sentido horário
    init.angle = 90)           # Inicia o desenho no topo (12 horas)

# 6. Adicionar uma legenda detalhada ao lado
legend("bottom", 
       legend = labels_custom, 
       fill = cores, 
       title = "Categorias de Status",
       cex = 0.7,              # Reduz o tamanho da fonte da legenda
       ncol = 2,               # Organiza em 2 colunas para economizar espaço
       bty = "n")              # Remove a caixa ao redor da legenda

Detalhes técnicos desta visualização:

  • table(storms$status): Consolida as categorias para o cálculo das fatias.

  • labels = NA: Omitimos os rótulos diretamente nas fatias porque muitos nomes se sobreporiam. Em vez disso, calculamos as porcentagens manualmente.

  • rainbow(): Gera uma gama de cores distintas para cada um dos diferentes status presentes na base.

  • init.angle = 90: Alinha o início da primeira fatia ao topo do círculo, o que é um padrão estético comum.

  • legend(): Adicionamos a legenda na parte inferior (bottom) com duas colunas (ncol = 2) para garantir que todas as categorias (como “hurricane”, “tropical storm”, etc.) fiquem visíveis sem poluir o gráfico.

5.1.7 Gráfico de barras

Também é construído de forma semelhante ao de pizza, onde são necessários os valores para cada situação.

# 1. Preparação dos dados: contar frequências da coluna 'status'
status_freq <- table(storms$status)

# 2. Ordenar as barras da maior para a menor (opcional, para melhor visualização)
status_freq <- status_freq[order(status_freq, decreasing = TRUE)]

# 3. Definir uma paleta de cores personalizada
cores <- terrain.colors(length(status_freq))

# 4. Ajustar as margens do gráfico para que os nomes longos caibam no eixo X
# mar = c(bottom, left, top, right)
par(mar = c(9, 5, 4, 2)) 

# 5. Criar o gráfico com a função plot (ou barplot para maior controle)
bp <- barplot(status_freq,
        main = "Distribuição de Status das Tempestades (Base storms)", # Título
        #sub = "Fonte: NOAA Dataset",          # Subtítulo 
        ylab = "Frequência Absoluta",          # Título eixo Y
        cex.axis = 0.7,                        # Reduz tamanho dos números do eixo
        col = cores,                           # Cores das barras
        border = "darkgray",                   # Cor da borda
        las = 2,                               # Rotacionar texto eixo X (vertical)
        cex.names = 0.8,                       # Tamanho da fonte dos nomes
        ylim = c(0, max(status_freq) * 1.2))  # Aumentar topo para caber os números

# 6. Adicionar grade horizontal para facilitar a leitura
grid(nx = NA, ny = NULL, col = "gray", lty = "dotted")

# 7. Adicionar os valores exatos acima de cada barra
text(x = bp, 
     y = status_freq, 
     label = status_freq, 
     pos = 3, 
     cex = 0.7, 
     col = "darkblue", 
     font = 2)

# 8. Resetar as configurações de margem padrão (boa prática)
# dev.off() ou par(mar = c(5, 4, 4, 2) + 0.1)

Detalhes técnicos desta visualização:

table(storms$status): Transforma os dados brutos em uma tabela de contagem necessária para o gráfico.

par(mar = …): Aumenta o espaço inferior (bottom) para evitar que os nomes das categorias (que são longos em storms) sejam cortados.

las = 2: Gira as etiquetas do eixo X em 90 graus, tornando-as legíveis.

ylim: Definimos o limite do eixo Y um pouco acima da maior barra para garantir que o texto dos números (text) não fique cortado no topo.

pos = 3: Posiciona o texto exatamente “acima” das coordenadas Y fornecidas.

grid(): Adiciona linhas de referência que tornam o gráfico mais técnico e fácil de interpretar.

5.1.8 Criando curvas

Utilize a função curve para produzir gráficos com curvas matemáticas conhecidas. Veja o exemplo:

# FUNÇÃO CURVE

curve(x^2, col = "blue")
curve(x^3, col = "green", add = T)
curve(x^4, col = "red", add = T)

5.1.9 Organizando os seus gráficos

A função X11() abre um novo canvas para você publicar seus gráficos enquanto a função dev.off() desliga esse canvas. Por sua vez, a função par() você organiza seus gráficos.

# Edita as margens do gráfico
par(mar= c(10,10,3,3))

# Organiza vários gráficos em um só canva.
par(mfrow=c(2,2)) # um canvas com 4 gráficos, 2 linhas e 2 colunas

5.2 Função ggplot2

Para trabalharmos gráficos com o ggplot é necessária a instalação da library(ggplot2). Não esqueça de verificar se ela está intalada e, se não tiver, instale.

A função ggplot utiliza uma estrutura em camadas que permite ir agregando “funcionalidades”.
A sua função básica é a ggplot() é a funçã base.

A função aes() define o espaço onde serão plotadas as informações.
Algumas características o aes são:
- x - posição no eixo x;
- y - posição no eixo y;
- shape - tipo dos marcadores (pontos, quadrados, cruzes, etc);
fill - “cor de dentro” do objeto;
- color - cor do contorno dos objetos internos do gráfico (barras,…);
- alpha - nível de transparência dos objetos;
- size - tamanho dos objetos.

A função geom() possui uma infinidade de funcionalidades. Destado agumas mais relevantes:
- geom_abline() – Linhas de referência: horizontal, vertical e diagonal
- geom_bar() – Gráficos de barra
- geom_boxplot() – Cria um boxplot
- geom_density() – Estimativa de densidade kernel
- geom_density_2d() – Estimativa de densidade kernel 2d apresentando os resultados com contorno
- geom_dotplot() – Gráfico de pontos
- geom_label() – Texto
- geom_map() – Polígonos de um mapa de referência
- geom_path() – Conectar observações
- geom_point() – Pontos

Outras funcionalidades:
- geom_bin2d() – Mapa de calor das contagens de bin 2d
- geom_blank() – Plot em branco
- geom_contour() – 2D contornos de uma superfície 3d
- geom_count() – Conta pontos sobrepostos
- geom_crossbar() – Intervalos verticais: linhas, barras transversais e barras de erro
- geom_errorbarh() – Barras de erro horizontais
- geom_freqpoly() – Histogramas e polígonos de frequência
- geom_hex() – Mapa de calor hexagonal de contagens de bin 2d
- geom_jitter() – Pontos agitados
- geom_polygon() – Polígonos
- geom_qq_line() – Um gráfico quantil-quantil
- geom_quantile() – Regressão quantílica
- geom_raster() – Retângulos
- geom_ribbon() – Fitas e gráficos de área
- geom_rug() – Parcelas de tapete nas margens
- geom_segment() – Segmentos de linhas e curvas
- geom_smooth() – Meios condicionais suavizados
- geom_spoke() – Segmentos de linha parametrizados por localização, direção e distância
- geom_violin() – Trama de violino

Alguns temas para dar estilo aos seus gráficos:
- theme_classic()
- theme_bw()
- theme_grey()
- theme_gray()
- theme_linedraw()
- theme_light()
- theme_minimal()
- theme_dark()

5.2.1 Aplicando a função ggplot2

Serão apresentadas as funções paulatinamente:

Função ggplot():

# Cria um espaço para os gráficos e associa os dados
ggplot(storms)

O sinal de **_ + _** no final da linha agrega às funções subsequentes, formando um comando único.

Funão aes():
A função aes tem seu nome derivado de “aesthetics”, que significa “estético” em Português.
Nela é especificado o canvas onde serão plotados os gráficos, assim como seus eixos e características.

ggplot(storms) +
  aes(year, wind)

5.2.2 Gráfico de pontos - scaterplot

geom_point()

ggplot(storms) +
  aes(year, wind) +
  geom_point()

Para configurarmos o gráfico, podemos incluir informações nas funções:
Alterando as cores e o tamanho dos pontos.

ggplot(storms) +
  aes(year, wind, color = category, size = wind) +
  geom_point()

5.2.3 Gráfico de colunas

geom_col() desenha um gráfico de colunas com 2 variáveis, x, y.

ggplot(storms) +
  aes(year, wind, color = year) +
  geom_col() 

5.2.4 Gráfico de barras

geom_bar() desenha um gráfico de barras somente com um eixo, no caso o \(x\). O eixo \(y\) indica a contagem de registros de ventos com a intensidade marcada em \(x\).

ggplot(storms) +
  aes(wind) +
    geom_bar(color = "blue", fill = "yellow") 

5.2.5 Histograma

geom_hitogram() é um gráfico de barras onde controlo os intervalos das barras no eixo \(x\). No caso, defini 15 barras, bins = 15.

ggplot(storms) +
    aes(wind) +
    geom_histogram(bins = 15, color = "green", fill = "white")

Mudando o intervalo da barra e colocando um tema no histograma.

ggplot(storms) +
  aes(wind) +
  geom_histogram(bins = 10) +
  theme_light()

5.2.6 Boxplot

geom_boxplot()
Boxplot do vento geral.

 ggplot(storms) +
    aes(wind) +
    geom_boxplot() 

Primeiro, o R calcula as estatísticas básicas do conjunto de dados:
Q1 (1º Quartil): O valor abaixo do qual estão 25% dos dados.
Q3 (3º Quartil): O valor abaixo do qual estão 75% dos dados.
IQR (Intervalo Interquartil): A diferença entre o terceiro e o primeiro quartil - essa é a região do box.
\[IQR = Q3 - Q1\]

O geom_boxplot desenha “hastes” (whiskers) que se estendem até os pontos mais distantes que não sejam outliers. Os limites teóricos para detectar outliers são:
Limite Inferior: \(Q1 - 1.5 \times IQR\)
Limite Superior: \(Q3 + 1.5 \times IQR\)

Um boxplot do vento (wind) por status da tempestade.
É necessário juntar uma seleção do dplyr onde é realizado o agrupamento por status e depois desenhar o gráfico com o ggplot.
Observe que:
- no dplyr as funções se conectam com %>% , enquanto no
- ggplot as funções se concectam com o _ + _.

storms %>%
  ggplot() +
      aes(wind, status, color = status) +
      geom_boxplot() 

5.2.7 Gráfico de linha

Em função dos dados, será necessária uma breve preparação dos dados, criando a média de pressão por mês.

storms_processado <- storms %>%
  group_by(month) %>%
  summarise(media_pressao = mean(pressure, na.rm = TRUE))
print(storms_processado)
## # A tibble: 10 × 2
##    month media_pressao
##    <dbl>         <dbl>
##  1     1          992.
##  2     4          998.
##  3     5         1004.
##  4     6         1002.
##  5     7         1001.
##  6     8          996.
##  7     9          990.
##  8    10          992.
##  9    11          992.
## 10    12          998.

A partir desses dados é possível criar gráficos legíveis.

ggplot(storms_processado) +
  aes(x = month, y = media_pressao) +
  geom_line(color = "steelblue", size = 1)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

É possível acrescentar outros gráficos, sum sobre o outro.

ggplot(storms_processado) +
  aes(x = month, y = media_pressao) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "darkred", size = 2)

Podemos ainda, agrupar esse gráfico por status. Para tal, devemos organizar os dados.

# 1. Agrupar por mês E por status
storms_status <- storms %>%
  group_by(month, status) %>%
  summarise(media_pressao = mean(pressure))

# 2. Criar o gráfico com cores diferentes para cada status
ggplot(storms_status, aes(x = month, y = media_pressao, color = status)) +
  geom_line(size = 1) +
  geom_point() +
  theme_light()

5.2.8 Configurando títulos e legendas

A função labs é utilizada para configurar títulos e legenda.
Veja os exemplos.

Veja o mesmo gráfico anterior com legendas e títulos.

ggplot(storms_status, aes(x = month, y = media_pressao, color = status)) +
  geom_line(size = 1) +
  geom_point() +
  labs(
    title = "Pressão Média por Mês e Status da Tempestade",
    subtitle = "Fonte: Autor",
    x = "Mês",
    y = "Pressão Média (mbar)",
    color = "Status"
  ) +
  theme_light()

Ainda é possível deixar a escala do eixo \(x\) contínua, variando de 1 a 12. Nesse caso, repare que existem meses que não possuem dados sobre determinado status, por isso não existem os pontos.

ggplot(storms_status, aes(x = month, y = media_pressao, color = status)) +
  geom_line(size = 1) +
  geom_point() +
  scale_x_continuous(breaks = 1:12) +
  labs(
    title = "Pressão Média por Mês e Status da Tempestade",
    x = "Mês",
    y = "Pressão Média (mbar)",
    color = "Status"
  ) +
  theme_light()

5.2.9 Facet

A facet_wrap e a facet_grid permitem a subdivisão das áreas de plotagem em diversos gráficos, conforme o tema de interesse.

O **_wrap** do grid se diferenciam pela organização dos gráficos.

Veja o exemplo anterior com a função facet_wrap().

ggplot(storms_status) +
  aes(x = month, y = media_pressao, group = status) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "steelblue") +
  # Criar um painel para cada status
  facet_wrap(~status, scales = "free_y") 

Incluindo legendas e títulos

ggplot(storms_status, aes(x = month, y = media_pressao, group = status)) +
  geom_line(color = "steelblue", size = 1) +
  geom_point(color = "steelblue") +
  # Criar um painel para cada status
  facet_grid(~status, scales = "free_y") + 
  scale_x_continuous(breaks = c(1, 4, 7, 10, 12)) +
  labs(
    title = "Evolução da Pressão Média Mensal por Categoria",
    subtitle = "Painéis individuais por status da tempestade",
    x = "Mês",
    y = "Pressão Média (mbar)"
  ) +
  theme_bw() +
  theme(strip.background = element_rect(fill = "gray90")) # Destaca os títulos dos quadros

Vejam os exemplos dos histogramas de ventos (wind) no decorrer dos anos anteriores a 2021.

storms %>%
  filter(year > 2012) %>%
ggplot() +
  geom_histogram(aes(wind), bins = 15) +
  facet_wrap(~ year) +
  theme_light()

Perceba a diferença entre o facet_grid e o facet_wrap.

storms %>%
  filter(year > 2012) %>%
ggplot() +
  geom_histogram(aes(wind), bins = 10) +
  facet_grid(~ year)+
  theme_light()

6 Tutorial RMarkdown

Este texto orientará na aplicação dos comandos básicos para o RMarkdown.

6.1 Cabeçalho

Os cabeçalhos, também chamados de metadados, orientam toda a produção do arquivo. Eles são gerados automaticamente quando se utiliza um arquivo rmd.No entanto é possível incluir linhas para alterar configurações.
Neles é possível alterar temas, letras, formatos, índices, ….
Deve-se ter muita atenção ao posicionamento das palavras em relação à margem (indentação), e a sequência dos comandos, pois podem gerar erros.
Abaixo um exemplo de cabeçalho com temas e comandos básicos.

Exemplo:

  • title: ”Exercícios Resolvidos - Básico”” - inclui o titulo no trabalho.
  • author: “Prof Adriano” - nome do autor - pode ser suprimido.
  • date: “2026-03-26” - atualiza a data toda vez que o documento é atualizado. Pode ser substituído por uma data permanente.Veja: abaixo.
  • date: “21 de abril de 2022”
  • output: - o que será gerado. É possível mudar o formato para word ou pdf.
  • html_document: - no caso, será gerado um documento html.
  • code_folding: show - funcionalidade que permite ao leitor “esconder” ou não os códigos.
  • number_sections: yes - numera automaticamente o documento com base nos títulos e subtítulos.
  • toc: yes
  • toc_float:
  • collapsed: yes
  • smooth_scroll: yes” - esconde os subitens do índice gerado.
  • theme:” - formata o fundo, letras e linhas.
  • bg: “#202123”” - define cor do fundo conforme palheta de cor.Busque a palheta de cores html no internet, lá será possível verificar os códigos das cores.
  • fg: “#B8BCC2”” - define a cor das letras.
  • primary: “#EA80FC”” - cor da letra dos links.
  • secondary: “#00DAC6”” - define a cor do fundo secundário, por exemplo as caixas de texto do “Code”.
  • base_font:
  • google: Prompt” - esta linha e de cima definem a fonte utilizada no texto.
  • heading_font:
  • google: Proza Libre” - esta e a linha de cima definem a fonte utilizada nos títulos.

Veja a imagem de um cabeçalho válido.
Cabeçalho

6.2 Configurações dos chunks

  • eval = FALSE - para não avaliar o código, apenas mostrar.
  • echo = FALSE - omite o código, mostra apenas as saídas.
  • results = “hide” - para não mostrar as saídas, os resultados do código.
  • warning = FALSE e message = FALSE suprime as mensagens de aviso.
  • fig.width = 3 e fig.height = 3 para alterar o tamanho dos gráficos gerados pelo R (em polegadas)
  • cache = TRUE armazena os resultados e evita que eles sejam executados todas as vezes que o documento é compilado - normalmente cria uma pasta para isso, além do arquivo gerado.

6.3 Marcação de texto

6.3.1 Títulos

Poderão ser numerados automaticamente caso esteja incluída a linha number_sections: yes.

# Título
## Sub-título
### Sub-sub-título

# Título
## Sub-título
### Sub-sub-título

6.3.2 Itálico, negrito, taxado e sobrescrito

# Itálico       
# *Italico*    
# _Itálico_    

Itálico
Italico  
Itálico  

# Negrito   
# **Negrito**       
# __Negrito__

Negrito   Negrito  
Negrito

# Tachado       
# ~~Tachado~~

Tachado   Tachado

# Texto Sobrescrito       
# Texto^Sobrescrito^

Texto Sobrescrito  
TextoSobrescrito

Parágrafo
Para gerar um novo parágrafo é necessário:
- pular uma linha;
- ou dar 3 espaços;
- ou pressionar 2 vezes a techa TAB ao final do parágrafo;
- ou incluir o sinal a barra invertida no fim do parábrafo “".

Lista  
- Primeiro da lista
- Segundo da lista
- Terceiro da lista

Lista ordenada
1. Primeiro item
2. Segundo item
3. Terceiro item

6.5 Imagem

Para usar uma imagem da web:

#![legenda da imagem](link da imagem)
Logo do R do computador
Logo do R do computador
Logo do R - da web
Logo do R - da web

6.6 Tabela

Veja o código:
Tabela

Cabeçalho Cabeçalho 2
Célula 1 Célula 2
Célula 3 Célula 4

Para alinhar as colunas:

  • Alinhar à esquerda: :—
  • Alinhar ao centro: :—:
  • Alinhar à direita: —:
Esquerda Centro Direita
Célula Célula Célula

6.6.1 Tabela com função kable

Uma outra forma de apresentar uma tabela é utilizando a função kable. Considero essa forma mais simples.
A biblioteca para a utilização da função kable é a kableExtra.

library(kableExtra)


É necessário fazer um data.frame dessa tabela e em seguida chamar esse data.frame da função kable.
Exemplo:

# Criando o data.frame
tabela <- data.frame(Esquerda = c("Nome da linha", "Nome da linha"), 
                     Centro = c("Célula1", "Célula2"), 
                     Direita = c(3, 4))

kable(tabela)
Esquerda Centro Direita
Nome da linha Célula1 3
Nome da linha Célula2 4


Para criar o chunk omitindo o código e aparacendo o resultado da tabela, coloque na primeira linha do chunk o seguinte comando: ```{r, echo=TRUE, results=‘hold’}.

Veja como ficam os mesmos comandos aplicando-se essa orientação:

Esquerda Centro Direita
Nome da linha Célula1 3
Nome da linha Célula2 4


Obs: para nomes compostos com espaços, é necessário colocá-los entre aspas, caso contrário o código gerará erro.

6.6.1.1 Formatando a função kable

A função kable tem argumentos que permitem sua formatação. Veja quais são:

digits: é o número máximo de dígitos para as colunas numéricas.
Exemplo:

tabela <- data.frame(Esquerda = c("Nome da linha", "Nome da linha"), 
                     "Coluna do Centro" = c(1.589742, 2.123456789), 
                     Direita = c("Célula 3", "Célula 4"))

kable(tabela, digits = 2)
Esquerda Coluna.do.Centro Direita
Nome da linha 1.59 Célula 3
Nome da linha 2.12 Célula 4


align: é um vetor com o alinhamento das colunas.
- “l” (esquerda - left);
- “c” (centro - center); e/ou
- “r” (direita - right).
Exemplo:

tabela <- data.frame(Esquerda = c("Nome da linha", "Nome da linha"), 
                     "Coluna do Centro" = c(1.589742, 2.123456789), 
                     Direita = c("Célula 3", "Célula 4"))

kable(tabela, align = c("r","c","l"), digits = 2)
Esquerda Coluna.do.Centro Direita
Nome da linha 1.59 Célula 3
Nome da linha 2.12 Célula 4


caption: inlcui um título para a tabela.
Exemplo:

tabela <- data.frame(Esquerda = c("Nome da linha", "Nome da linha"), 
                     "Coluna do Centro" = c(1.589742, 2.123456789), 
                     Direita = c("Célula 3", "Célula 4"))

kable(tabela, caption = "TABELA EXEMPLO", align = c("r","c","l"), digits = 3)
TABELA EXEMPLO
Esquerda Coluna.do.Centro Direita
Nome da linha 1.590 Célula 3
Nome da linha 2.123 Célula 4


padding: aumenta o espaçamento entre as colunas da tabela.
Exemplo:

tabela <- head(iris,3)
kable(tabela,
      padding=5)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa


format: podemos atribuir diversos formatos com o comando format. O formato pipe é o padrão.
Outros formatos:
- latex
- html
- rst
- simple
Exemplo:

d1 = head(iris,3)
kable(d1, caption = "formato padrão")
formato padrão
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa


kable(d1, format = "pipe", caption = "formato pipe")
formato pipe
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa


kable(d1, format = "simple", caption = "formato simple")
formato simple
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa

Organizando tabelas com o comando list:
Exemplo:

d1 <- head(iris,3)
d2 <- tail(mtcars, 3)

# Com comando kable e list
kable(list(d1, d2), caption = "DUAS TABELAS LADO A LADO")
DUAS TABELAS LADO A LADO
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
mpg cyl disp hp drat wt qsec vs am gear carb
Ferrari Dino 19.7 6 145 175 3.62 2.77 15.5 0 1 5 6
Maserati Bora 15.0 8 301 335 3.54 3.57 14.6 0 1 5 8
Volvo 142E 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2


Foramtando decimais e separador de milhar.
Exemplo:

# O comando "matrix" dentro do data.frame cria uma matriz de 20 elementos e 5 linhas de números aleatórios com distribuição normal
x = as.data.frame(matrix(rnorm(20, 1e+06, 1000), 5))
kable(x, format.args = list(decimal.mark = ",", big.mark = "."), format = "simple")
V1 V2 V3 V4
1.000.972 998.979,7 999.186,4 999.926,4
1.000.091 999.469,3 998.786,1 1.000.961,0
1.000.331 999.162,8 999.518,3 999.996,6
1.000.007 1.000.726,2 999.568,3 999.083,3
1.000.482 1.000.694,4 999.316,7 999.532,7

6.7 Equações matemáticas

Equações na própria linha podem ser inseridas entre $:
Exemplo:

# Um modelo de equação:  $y = \beta_0 + \beta_1 x + \epsilon$.

Veja o código dentro do texto:
Um modelo de regressão linear simples: \(Y = \beta_0 + \beta_1 x + \epsilon\).

Um conjunto de equações pode ser exibido entre $$:
Veja o código:

# Texto.....
# $$
# f(x;\mu,\sigma^2) = \frac{1}{\sigma\sqrt{2\pi}}
# e^{ -\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^2 }
# $$
# Texto.....

Veja o código acima inserido no texto:
\[ f(x;\mu,\sigma^2) = \frac{1}{\sigma\sqrt{2\pi}} e^{ -\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^2 } \]
Entendendo o código acima:

frações:
Veja o código: Código de frações

Veja no texto:
\(\frac{x-\mu}{\sigma}\)

letras gregas:

Veja o código: Código de letras gregas

Veja no texto: \(\sigma, \alpha_0, \alpha_1, \delta_0, \beta_0, \beta_1, \epsilon, \mu, \mu_0, \pi\).

raíz quadrada:

Veja o código:
Código de raíz quadrada
Veja no texto: \(\sqrt{2\pi}\)

exponenciação: Veja o código:
Código de exponenciação
Veja no texto: \(\sigma^2\).

7 Programação Linear (PL)

Existem vários programas para resolver problemas de programação linear (PL):
- lpSolve;
- Rglpk;
- Rsymphony
Alguns destes pacotes têm funções que permitem a leitura de arquivos contendo problemas de programação linear, programação linear inteira e programação linear inteira mista escritos no formato CPLEX, por exemplo.

library(lpSolve)

7.1 Exercício

Uma pequena empresa vende dois produtos, Produto 1 e Produto 2.
Cada tonelada do Produto 1 consome 30 horas de trabalho e cada tonelada do Produto 2 consome 20 horas de trabalho. A empresa tem no máximo 2700 horas de trabalho para o período considerado.
Além disso, cada tonelada dos Produtos 1 e 2 consome 5 e 10 horas de máquina para processar a matéria prima, respectivamente. Sabe-se que a empresa tem 850 horas disponíveis para processamento da matéria prima.
Cada tonelada vendida do Produto 1 gera 20 mil reais de lucro enquanto para o Produto 2 o valor é de 60 mil reais.
Por razões técnicas a empresa deve produzir no mínimo um total de 95 toneladas. Nosso objetivo é saber quantas toneladas dos dois produtos devem ser produzidas para maximar o lucro total da empresa.

O problema exposto pode ser escrito da seguinte forma:

7.1.1 Modelagem do Problema

Max: 20000P1 + 60000P2
sa:
30P1 + 20P2 <= 2700
5P1 + 10P2 <= 850
P1 + P2 >= 95

P1 P2 Rest
30 20 2700
5 10 850
1 1 95

7.1.2 Solucção do problema

# coeficientes de P1 e P2 na função objetivo 
func.objetivo <- c(20000 , 60000) # c' 
# coeficientes de P1 e P2 nas restrições. Sempre em matriz como mostrado no texto acima
coeficientes.restricoes <- matrix (c(30, 20, 5, 10, 1, 1), ncol = 2 , byrow = TRUE) # Matriz A
# sinal das restrições. Deve obedecer a ordem da matriz de coeficientes
direcao.restricoes <- c("<=","<=",">=")
# limite das restrições. Deve obedecer a ordem da matriz de coeficientes
limites.restricoes <- c(2700, 850, 95) # vetor b
##########################
####     SOLUÇÃO     #####
##########################
# Basicamente, usamos a função lp do pacote lpSolve 
# com os seguintes parâmetros:
# direction: que recebe max ou min dependendo se o problema é 
# de maximização ou minização, respectivamente
# objective.in: que recebe o nome do vetor com parâmetros da função objetivo
# const.mat: que recebe o nome da matriz com coeficientes das restrições
# const.rhs: que recebe o nome do vetor com os limites das restrições
# mais opções da função podem ser obtidas por meio do help(lp)
solucao.problema <- lpSolve::lp(direction = "max",             
                                objective.in = func.objetivo,  
                                const.mat = coeficientes.restricoes,
                                const.dir = direcao.restricoes,
                                const.rhs = limites.restricoes)
# ou
solucao.problema <- lp("max", func.objetivo, coeficientes.restricoes, 
                       direcao.restricoes, limites.restricoes)

7.1.3 Resultados

Os resultado são:

função objetivo e valores para P1 e P2

solucao.problema$objval
## [1] 4900000
solucao.problema$solution
## [1] 20 75

7.2 Exercício

A Reggio Advertising Company deseja planejar uma campanha publicitária em três meios diferentes - televisão, rádio e revistas. O objetivo da publicidade é alcançar tantos clientes em potencial quanto possível. Os resultados de um estudo de mercado são fornecidos abaixo:

Custos e clinetes TV Diurna TV Hor. Nobre Rádio Revistas
Custo de 1 publicidade por unidade $40.000 $75.000 $30.000 $ 15.000
N. pot clientes alcançados p/ un 400.000 900.000 500.000 200.000
N. mulheres alcançados por un 300.000 400.000 200.000 100.000

A empresa não quer gastar mais do que $800.000 na publicidade. Além disso, requer que:
(1) pelo menos 2 milhões as exposições ocorrem entre mulheres;
(2) publicidade em televisão seja limitada a $ 500.000;
(3) pelo menos 3 publicidades sejam compradas na televisão diurna, e duas unidades durante horário nobre; e
(4) o número de unidades de publicidade no rádio e em revistas deve ser entre 5 e 10.

Formular o problema de programação linear.

7.2.1 Modelagem do Problema

Sejam x1, x2, x3 e x4 o número de unidades de publicidade compradas televisão diurna, televisão em horário nobre, rádio e revistas, respectivamente.

O número total de clientes potenciais alcançados (em milhares) = 400x1 + 900x2 + 500x3 + 200x4.

A restrição à publicidade orçamento é representado por:
40.000x1 + 75.000x2 + 30.000x3 + 15.000x4 ≦ 800.000.

A restrição no número de clientes mulheres alcançadas pela campanha publicitária torna-se: 300.000x1 + 400.000x2 + 200.000x3 + 100.000x4 ≧ 2.000.000.

As restrições à publicidade na televisão são:
40.000x1 + 75.000x2 ≦ 500.000
x1 ≧ 3
x2 ≧ 2.
Uma vez que as unidades de publicidade em rádio e revistas devem ter cada uma entre 5 e 10, obtém-se as seguintes restrições:
5 ≦ x3 ≦ 10
5 ≦ x4 ≦ 10.

O problema de programação linear completo com algumas pequenas simplificações é dado abaixo (para facilitar o entendimento cortei 3 zeros):
Maximizar: Z = 400x1 + 900x2 + 500x3 + 200x4.
Sujeito a:
40x1 + 75x2 + 30x3 + 15x4 ≦ 800
300x1 + 400x2 + 200x3 + 100x4 ≧ 2.000
40x1 + 75x2 ≦ 500
x1 ≧ 3
x2 ≧ 2
x3 ≧ 5
x3 ≦ 10
x4 ≧ 5
x4 ≦ 10
  Vamos colocar os coeficientes da FO, das variáveis das restrições e as restrições em matrizes:
Variáveis x1 x2 x3 x4 Restrições

FO 400 900 500 200

Restrições 40 75 30 15 ≦ 800
300 400 200 100 ≧ 2.000
40 75 ≦ 500
1 ≧ 3
1 ≧ 2
1 ≧ 5
1 ≦ 10
1 ≧ 5
1 ≦ 10

Fazemos uma matriz para cada linha da formulação acima. Os espaços vazios completamos com zeros.

func.objetivo <- c(400, 900, 500, 200)

coeficientes.restricoes <- matrix (c(40, 75, 30, 15,
300, 400, 200, 100,
40, 75, 0, 0,
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 0, 1,
0, 0, 0, 1),
ncol = 4,
byrow = TRUE)
 
Criamos um vetor com o sinal das restrições. Deve obedecer a ordem da matriz de coeficientes direcao.restricoes <- c(“<=”,“>=”,“<=”,“>=”, “>=”, “>=”, “<=”, “>=”,“<=”)

Por fim, criamos um vetor com o limite das restrições que deve obedecer a ordem da matriz de coeficientes.
limites.restricoes <- c(800, 2000, 500, 3, 2, 5, 10, 5, 10)
O problema está pronto! Agora é só chamar a função lp:
solucao.problema <- lp(“max”, func.objetivo, coeficientes.restricoes, direcao.restricoes, limites.restricoes)

7.2.2 Solução do Problema

# Função Objetivo (FO)
func.objetivo <- c(400, 900, 500, 200) 

# Matriz com os coeficientes das variáveis de decisão das restrições
coeficientes.restricoes <- matrix (c(40,  75,  30,  15, 
                                    300, 400, 200, 100, 
                                    40,   75,   0,   0, 
                                     1,    0,   0,   0, 
                                     0,    1,   0,   0, 
                                     0,    0,   1,   0, 
                                     0,    0,   1,   0, 
                                     0,    0,   0,   1, 
                                     0,    0,   0,   1),  
                                     ncol = 4,  
                                     byrow = TRUE) 

# Vetor com os sinais das restrições
direcao.restricoes <- c("<=",">=","<=",">=", ">=", ">=", "<=", ">=","<=")  

# Vetor com os valores das restrições
limites.restricoes <- c(800, 2000, 500, 3, 2, 5, 10, 5, 10)

# REsolvendo o problema
solucao.problema <- lp("max", func.objetivo, coeficientes.restricoes, 
                       direcao.restricoes, limites.restricoes)

7.2.3 Resultados

O resultado, armazenado na variável solucao.problema é uma lista com todos os dados disponíveis.
Vaja os dados contidos nessa variável e como são chamados os valores da solução.

# Vendo a variável solucao.problema
head(solucao.problema, 28)
## $direction
## [1] 1
## 
## $x.count
## [1] 4
## 
## $objective
## [1] 400 900 500 200
## 
## $const.count
## [1] 9
## 
## $constraints
##               [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
##                 40  300   40    1    0    0    0    0    0
##                 75  400   75    0    1    0    0    0    0
##                 30  200    0    0    0    1    1    0    0
##                 15  100    0    0    0    0    0    1    1
## const.dir.num    1    2    1    2    2    2    1    2    1
## const.rhs      800 2000  500    3    2    5   10    5   10
## 
## $int.count
## [1] 0
## 
## $int.vec
## [1] 0
## 
## $bin.count
## [1] 0
## 
## $binary.vec
## [1] 0
## 
## $num.bin.solns
## [1] 1
## 
## $objval
## [1] 10960
## 
## $solution
## [1]  3.000000  3.066667 10.000000 10.000000
## 
## $presolve
## [1] 0
## 
## $compute.sens
## [1] 0
## 
## $sens.coef.from
## [1] 0
## 
## $sens.coef.to
## [1] 0
## 
## $duals
## [1] 0
## 
## $duals.from
## [1] 0
## 
## $duals.to
## [1] 0
## 
## $scale
## [1] 196
## 
## $use.dense
## [1] 0
## 
## $dense.col
## [1] 0
## 
## $dense.val
## [1] 0
## 
## $dense.const.nrow
## [1] 0
## 
## $dense.ctr
## [1] 0
## 
## $use.rw
## [1] 0
## 
## $tmp
## [1] "Nobody will ever look at this"
## 
## $status
## [1] 0
# Chamando somente o valor da função obejtivo
solucao.problema$objval
## [1] 10960
# Chamando o valor das variáveis de decisão para a solução ótima
solucao.problema$solution
## [1]  3.000000  3.066667 10.000000 10.000000

7.3 Exercício

Considere que existem 3 silos que são necessários para satisfazer a demanda de 4 fábricas (Mills), conforme tabela a seguir. (Um silo é uma área de armazenamento da fazenda usada para armazenar grãos e Moinho é uma fábrica de moagem de grãos).
Determine o quanto de cada silo deve ir para cada fábrica afim de que o custo de transporte seja minimizado.

FROM MIL1 MIL2 MIL3 MIL4 SUPLLY :——:|:—–:|:——:|:——:|:——:——-: SIL1 | 10 | 2 | 20 | 11 | 15 SIL2 | 12 | 7 | 9 | 20 | 25 SIL3 | 4 | 14 | 16 | 18 | 10 DEMAND | 5 | 15 | 15 | 15 | 15


FROM Mil1 Mil2 Mil3 Mil4 Supply
Silo1 10 2 20 11 15
Silo2 12 7 9 20 25
Silo3 4 14 16 18 10
Demanda 5 15 15 15 15

7.3.1 Modelagem do Problema

Esse é típico problema de fluxo.
- As variáveis de decisão são os fluxos que saem dos silos e chegam às fábricas - silo 1 para fábrica 1 (s11); silo 2 para a fábrica 1 (s21); silo 3 para a fábrica 1 (s31), …. Os coeficientes dessas variáveis são os valores da matriz apresentada acima. - As restrições são os valores marginais da matriz, supply e demand. Esses valores são explicados da seguinte forma:
- A quantidade de insumo que sai de um silo é a soma do seu fornecimento para todas as fábricas.
- A quantidade de insumo que chega em uma fábrica é a soma dos insumos que chegam de todos os silos.

O modelo é:
MIN 10S11 + 2S12 + 20S13 + 11S14 + 12S21 + 7S22 + 9S23 + 20S24 + 4S31 + 14S32 + 16S33 + 15S34

Sa:
s11 + s12 + s13 + s14 = 15
s21 + s22 + s23 + s24 = 25
s31 + s32 + s33 + s34 = 10
s11 + s21 + s31 = 5
s12 + s22 + s32 = 15 s13 + s23 + s33 = 15
s14 + s24 + s34 = 15

7.3.2 Solução do Problema

fo <-               c(10, 2, 20, 11, 12, 7, 9, 20, 4, 14, 16, 15)
coef_rest <- matrix(c(1,1,1,1,0,0,0,0,0,0,0,0,
                      0,0,0,0,1,1,1,1,0,0,0,0,
                      0,0,0,0,0,0,0,0,1,1,1,1,
                      1,0,0,0,1,0,0,0,1,0,0,0,
                      0,1,0,0,0,1,0,0,0,1,0,0,
                      0,0,1,0,0,0,1,0,0,0,1,0,
                      0,0,0,1,0,0,0,1,0,0,0,1
                      ), ncol = 12, byrow = TRUE)
direcao <- c("=","=","=","=","=","=","=")
rest <- c(15, 25, 10, 5, 15, 15, 15)

solucao <- lp("min",fo, coef_rest, direcao, rest)

7.3.3 Resultados

A solução é:
O valor da função objetivo é ‘r solucao$objval’

solucao$objval
## [1] 420
solucao$solution
##  [1]  0  5  0 10  0 10 15  0  5  0  0  5

8 Modelos de Previsão

A teoria apresentada se baseia em fundamentos encontrados nas referências citadas abaixo.

REFERÊNCIAS:

MOORE, J. H; WEATHERFORD, L. R. Tomada de decisão em administração com planilhas eletrônicas. 6 ed. Porto Alegrue: Bookman, 2005. Cap. 13.

BALLOU, Ronald H. Gerenciamento da Cadeia de Suprimentos: Logística Empresarial. Bookman, 2009. Cap. 8.

NIELSEN, Aileen. Análise prática de speries temporais: predição com estatística e aprendizado de máquina. Rio de Janeiro: Alta Books. 2021.

BARROS, A. C.; MATTOS, D. M.; OLIVEIRA, I. C. L.; FERREIRA, P. G. C.; DUCA, V. E. L. A.; Análise de Séries Temporais em R: curso introdutório. Organização Pedro Guilherme Costa Ferreira. 1ª ed. São Paulo: Editora Atlas, FGV IBRE, 2021. 264 p.

BIBLIOTECAS:
As bibliotecas utilizadas para o desenvolvimento dos cálculos são:

library(ggplot2) - gráficos
library(zoo)
library(data.table)
library(dplyr) - manipulação de dados
library(naivebayes) - redes neurais
library(neuralnet) - redes neurais
library(quantmod)   #library(fpp) - dados de séries temporais - 1ª edição
library(fpp2) - dados de séries temporais - 2ª edição
library(fpp3) - dados de séries temporais - 3ª edição
library(forecast) - previsões
#library(DMwR2)
library(stats)   library(plogr)
library(psych) - estatística - correlações

INTRODUÇÃO:

As previsões têm aplicações em diversas áreas do conhecimento humano. Em pesquisa científicas a criação de modelos e relacionamento de variáveis é rico para melhor compreensão dos fenômenos. Em Ciências Políticas e Relações Internacionais elas contribuem para compreensão dos ambientes estudados. Nas engenharias, a compreensão dos modelos e cálculos precisos permitem que se crie, projete e construacom segurança e qualidade. Na Administração, as previsões são úteis em diversas atividades,na compra de insumos, na previsão de demandas e estoques, no planejamento da produção, no planejamento financeiros, nas delimitações de mercado, na gestão de pessoas, enfim, em muitas e muitas atividades.
A compreensão dos diversos entendimentos sobre previsão são muito importantes para que possa compreender como estudar o futuro e empregar um modelo aderente à realidade que se quer estudar. Nesse sentido, apresentaremos algumas classificações dos modelos de previsão e em seguida nos aprofundaremos em alguns modelos quantitativos.
Segundo Ballou (2009), os métodos de previsão são divididos em três categorias: qualitativos, de projeção histórica e causais. Cada uma dessas categorias trabalham com diferentes graus em termos de precisão de curto, médio e longo prazos.

Métodos Qualitativos recorrem a conhecimentos, criatividade, julgamentos, interações entre previsores, dados históricos, técnicas comparativas, enfim, uma infinidade de técnicas para realizar estimativas sobre o futuro. Eles são muito utilizados para situações em que se trabalha com médio e longo prazos.

Métodos de projeção histórica são utilizados quando existe uma base de dados histórica considerável para o estudo desejado. Tem como premissa que o futuro repetirá padrões passados e devido sua natureza, são muito utilizados em previsões de curto prazo. Como principal limitação desses modelos, autores citam que eles são reativos e retardam a compreensão de mudanças de padrões.

Métodos causais possuem como base a relação de variáveis relacionadas à variável que se pretende prever (variável dependente), por exemplo, com o tempo de uso de equipamentos elétricos pode-se prever o consumo de energia. O grande desafio desse modelo é identificar as variáveis causais (chamadas de variáveis independentes).

Ballou (2009, p. 245-248), apresenta um quadro resumo de técnicas selecionadas de previsão e na tabela abaixo podemos identificar algumas delas:

Síntese das técnicas
Método Descrição Horizonte
Delphi Especialistas consultados por sequencia de questionário. Qualitativo Médio-longo
Pesquisa de mercado Procedimento sistematizado, formal e consciente para evolução e testes de hipóteses sobre mercados Médio-longo
Estimativas de equipe de vendas Opiniões de equipe de vendedores Curto-médio
Média móvel A estimativa se baseia na média aritmética de períodos anteriores Curto
Ponderação exponencial Similar a média móvel, com mais peso aos períodos mais recentes Curto
Séries temporais Decompõe uma série de tempo em tendência, sazonalidade e ruídos ou erros - com grande eficiência para modelos de médio prazo - de 3 a 12 meses Curto-médio
Modelos de regressão Explica uma variável dependente, sobre a qual se deseja a previsão, por meio de outras variáveis chamadas explicativas ou independentes Curto-médio
Modelos econométricos Sistema de equações de regressão interdependentes que descreve alguns setores das atividades econômicas de vendas Curto-médio
Redes neurais Modelo de inteligência artificial baseado nos neurônios biológicos. É caracterizado pela capacidade de aprender com novos dados Curto
Análise do ciclo de vida Análise do crescimento e decaimento com base nas curvas S Médio-longo
\

8.1 Conhecendo os dados

Ao obter um conjunto de dados, o primeiro passo é entendê-lo e ajustá-lo para o emprego da técnica desejada. Neste tópico iremos tratar dados ausentes, mudança de frequência dos registros dos dados, suavização dos dados, compreender a sazonalidade dos dados e prevenir lookaheads não intencionais. Nossa referências para esses tópicos é Nielsen (2021).

8.2 Principais tipos de dados

O R pode trabalhar com uma infinidade de tipo de dados estruturados, isto é, dados organizados em formas de tabelas, normalmente oriundos de coletas de sistemas de informações, de pesquisas, de censos, ou de levantamentos diversos.Estes dados são organizados em arquivos de diversos formatos, dependendo das características dos seus analistas ou dos sistemas que os comportam.

Algumas vezes, para cada formato de arquivo, ou de estruturação, existe um pacote específico para a sua manipulação. O conhecimento desses pacotes específicos facilita sobremaneira a sua aplicação.

Podemos citar como os principais tipos de dados:

a. planilhas Excel - essas planilhas assumem formatos .xls ou .xlsx
b. arquivos texto - tem como os formatos mais comuns o .csv e o .txt
c. arquivos em formatos específicos de programas estatísticos - .sav, .dat
d. arquivos específicos para séries temporais - .ts, .xts e .rds são os mais comuns

Para a leitura desses arquivos o R possui uma função básica chamada read.table(). A partir do read.table() são criadas outras funções para leituras de tipos de arquivos específicos.
Para salvarmos os arquivos, de forma similar se utiliza o write.table do qual são derivadas funções para se salvar dados em formatos específicos.

Para a manipulação dos dados dentro do R se utiliza como principais estruturas:
- data.frame
- matrizes
- listas
- tibble
- ts - aplicado em séries temporais
- xts - evolução do ts, aplicado em séries temporais

8.2.1 Formato ts

O formato ts é uma estrutura de dados que possui características específicas para as séries temporais e tem associada uma diversidade de funções para o seu trato.
Vamos entender o formato ts na prática. Considere um vetor de vendas mensais:

vendas <- c(25,15,28,23,25,27,22,21,23,24,29,33,26,16,30,24,27,27,21,21,24,25,30,34)
vendas
##  [1] 25 15 28 23 25 27 22 21 23 24 29 33 26 16 30 24 27 27 21 21 24 25 30 34

Vamos transformar esse vetor para a estrutura de ts. Essa estrutura facilita o trabalho com séries temporais. Sugere-se que ao se trabalhar com séries temporais utilizem esse formato.

vendas <- ts(vendas)
vendas
## Time Series:
## Start = 1 
## End = 24 
## Frequency = 1 
##  [1] 25 15 28 23 25 27 22 21 23 24 29 33 26 16 30 24 27 27 21 21 24 25 30 34

Repare que esse estrutura de dados contém informações para facilitar as análises que um vetor simples não possui.
Também é possível utilizar funções específicas para séries temporais.
No entanto, é preciso definir quando a série começa, quando termina e qual é a frequência de dados do período que pretendemos analisar.
Por exemplo:
- ano, podemos ter a frequencia mensal (12), trimestral (4), semestral (2).
- mes, frequencia diária (30), quinzenal (2).
- semana, frequencia diária (7).
- dia, frequencia horária (24), ou de 6 em 6h (4).
- hora, minuto a minuto (60); 10 em 10 min (6).

No nosso exemplo, estamos utilizando um período de 1 ano com a freqencia mensal (12 meses no ano) e estamos supondo que nossa série começa em janeiro. Então, veja como ficam os parametros da função ts .

vendas <- ts(vendas, start = c(2021,1), frequency = 12)
vendas
##      Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 2021  25  15  28  23  25  27  22  21  23  24  29  33
## 2022  26  16  30  24  27  27  21  21  24  25  30  34

O formato utilizado foi:

ts(dados, start = c(ano, mes), frequency = 12)
Repare que ao definir a frequencia, o ano e o mês de início, a função já atribuiu o nome dos meses para os dados. E que o ano e mês final foi omitido, o que faz com que a função calcule automaticamente os períodos.

autoplot(vendas)

ausbeer # produção trimestral de cerveja na Australia de 1956 até 2010.
##      Qtr1 Qtr2 Qtr3 Qtr4
## 1956  284  213  227  308
## 1957  262  228  236  320
## 1958  272  233  237  313
## 1959  261  227  250  314
## 1960  286  227  260  311
## 1961  295  233  257  339
## 1962  279  250  270  346
## 1963  294  255  278  363
## 1964  313  273  300  370
## 1965  331  288  306  386
## 1966  335  288  308  402
## 1967  353  316  325  405
## 1968  393  319  327  442
## 1969  383  332  361  446
## 1970  387  357  374  466
## 1971  410  370  379  487
## 1972  419  378  393  506
## 1973  458  387  427  565
## 1974  465  445  450  556
## 1975  500  452  435  554
## 1976  510  433  453  548
## 1977  486  453  457  566
## 1978  515  464  431  588
## 1979  503  443  448  555
## 1980  513  427  473  526
## 1981  548  440  469  575
## 1982  493  433  480  576
## 1983  475  405  435  535
## 1984  453  430  417  552
## 1985  464  417  423  554
## 1986  459  428  429  534
## 1987  481  416  440  538
## 1988  474  440  447  598
## 1989  467  439  446  567
## 1990  485  441  429  599
## 1991  464  424  436  574
## 1992  443  410  420  532
## 1993  433  421  410  512
## 1994  449  381  423  531
## 1995  426  408  416  520
## 1996  409  398  398  507
## 1997  432  398  406  526
## 1998  428  397  403  517
## 1999  435  383  424  521
## 2000  421  402  414  500
## 2001  451  380  416  492
## 2002  428  408  406  506
## 2003  435  380  421  490
## 2004  435  390  412  454
## 2005  416  403  408  482
## 2006  438  386  405  491
## 2007  427  383  394  473
## 2008  420  390  410  488
## 2009  415  398  419  488
## 2010  414  374

8.3 Dados ausentes

Os dados ausentes são normais em bases de dados para séries temporais. Isso ocorre devido a dificuldade de sistematização na obtenção desses dados e as intercorrências naturais no processo de coleta.
Existem basicamente três técnicas para lidar com essas ausências:
- Imputação - ocorre quando preenchemos os dados ausentes com base nos registros existentes.  Podemos imputar os dados ausentes com médias móveis a partir dos dados anteriores, média móvel a partir dos dados posteriores ou com a média geral dos dados.
- Interpolação - quando estimamos os dados ausentes a partir dos dados vizinhos.
- Exclusão de períodos de tempo ou registros afetados - é a opção de não utilizar os registros ou períodos ausentes, excluíndo-os.

8.4 Técnicas de previsão

Apresentaremos as técnicas mais utilizadas para previsões, são elas: - Média móvel - Suavização exponencial simples - Séries temporais - Regressão múltipla - Redes neuronais

8.5 Média móvel


É um modelo de suavização exponencial bastante simples, no qual se calcula a média aritmética das observações mais recentes.

8.5.1 Média Móvel Simples (MMS)


É produzida com o cálculo de observações anteriores para determinação do futuro. Também podemos utilizar a média móvel apenas para a suavisação dos dados e facilitação de sua interpretação.

Em um caso extremo, pegando apenas a observação do dia anterior, para prever o dia seguinte, dizemos que o n é 1.
Conforme se aumenta o número de observações para o cálculo da média, mais lenta é a alteração da tendência.
Dessa forma, o valor do número de observações anteriores para o cálculo da média móvel deve estar de acordo com a aleatoriedade da série. Portanto, cresce de importância a avaliação do analista.

Um caso típico de média móvel simples foi o acompanhamento da pandemia de COVID-19 realizada pelos telejornais, nas quais eram apresentadas diariamente a média móvel semanal (7 dias).

8.5.1.1 Prática da Média Móvel Simples (MMS)


Considere a seguinte base de dados da demanda de uma empresa:

demanda <- data.frame(dia = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14), 
                      demanda = c(78,65,90,71,80,101,84,60,87,80,102,91,95,112))

kable(head(demanda,3), digits = 2, format = "simple")
dia demanda
1 78
2 65
3 90

Para calcularmos a média móvel 3, utilizaremos os dias 1, 2 e 3. Assim:
$MM_3 = (Demanda_1 + Demanda_2 + Demanda_3)/3 $
Considerando que queremos fazer uma previsão com 3 dias a frente, Vamos calular as médias móveis para os dias 15, 16 e 17 (esses dias não estão disponíveis no data.frame).

Para isso: 1. Vamos criar mais duas colunas, uma para o cálculo da média móvel e outra para a previsão (que é a média móvel do dia anterior).
2. Vamos criar mais 3 linhas para as previsões dos dias 15 até 17.
3. Vamos calcular a média móvel. a. Observe que para a média do dias 1, 2 e 3 repetirei os valores dos dias 1,2 e 3.
b. Para os dias a serem criado, completarei os valores com zero.

3.a)

# a.
# Criando as colunas para o cálculo da média móvel e para previsão.
demanda$media_movel <- rep(0, 14) 
demanda$previsao <- rep(0,14)

kable(head(demanda,3), digits = 2, format = "simple")
dia demanda media_movel previsao
1 78 0 0
2 65 0 0
3 90 0 0

3.b)

# b.
# Criando mais 3 dias, de 15 a 17 em um novo data.frame.
novas_linhas <- data.frame(dia = seq(15,17),
                           demanda = rep(0,3),
                           media_movel = rep(0,3),
                           previsao = rep(0,3))

# unindo os dois data.frames, demanda e novas linhas.
demanda <- rbind(demanda, novas_linhas)

# agora, vamos repetir os valores de demanda em media_movel, pois não tem sentido calcular a média móvel para dias que já se sabe a demanda.
demanda$media_movel[c(1:3)] <- demanda$demanda[c(1:3)]
kable(tail(demanda,5), digits = 2, format = "simple")
dia demanda media_movel previsao
13 13 95 0 0
14 14 112 0 0
15 15 0 0 0
16 16 0 0 0
17 17 0 0 0

Pronto, agora estamos em condições de fazer os cálculos utilizando uma lógica similar ao Excel:

# Utilizando uma lógica similar ao Excel, calculamos a média das 3 linhas anteriores e arrastaríamos até o fim da tabela. Para realizar esses cálculos no R, utilizamos o comando for para realizar essa ação
for(i in 4:17){
  demanda$media_movel[i] <- 
    (demanda$demanda[i-1] +
       (ifelse(demanda$demanda[i-2]!=0,demanda$demanda[i-2],demanda$media_movel[i-2])) + 
       (ifelse(demanda$demanda[i-3]!=0,demanda$demanda[i-3],demanda$media_movel[i-3]))
     )/3
}
# O comando ifelse serve para capturar os valores de demanda enquanto existirem,
# Quando a demanda é zero (não existe) eu tenho que utilizar os valores da média móvel

# Agora só falta copiar o cálculo da média móvel para a previsão do dia seguinte. Ou seja média móvel do dia 15 é a previsão do dia 16.
demanda$previsao[c(5:17)] <- demanda$media_movel[c(4:16)]

kable(demanda, digits = 2, format = "simple")
dia demanda media_movel previsao
1 78 78.00 0.00
2 65 65.00 0.00
3 90 90.00 0.00
4 71 77.67 0.00
5 80 75.33 77.67
6 101 80.33 75.33
7 84 84.00 80.33
8 60 88.33 84.00
9 87 81.67 88.33
10 80 77.00 81.67
11 102 75.67 77.00
12 91 89.67 75.67
13 95 91.00 89.67
14 112 96.00 91.00
15 0 99.33 96.00
16 0 69.00 99.33
17 0 70.44 69.00

Vamos verificar graficamente como ficou a previsão:

# Vamos criar um gráfico com os dados e acrescentar uma linha com as previsões
plot(demanda$demanda[1:14], type='l', lwd=1, 
     xlim=c(1,17), ylim=c(60,115), 
     xlab = "Dias", ylab = "Demanda") 
  lines(demanda$media_movel, col=2, lwd=2, lty=2) 
  lines(demanda$previsao,  col=3, lwd=3, lty=3)
  legend(1,115,
         c("Demanda", "Suavização - MM", "Previsão"),
         lty = c(1, 2, 3),           # Line types
         col = c(1, 2, 3),           # Line colors
         lwd = c(1, 2, 3))

8.5.1.2 Função rollmean para cálculo de média móvel simples

O R já dispõe de um pacote que permite o cálculo da média móvel simples, é o zoo e a função é a rollmean.

Assim a biblioteca necessária é a:
zoo, com o comando library(zoo) depois que o pacote estiver instalado.

Os parâmetros da função são:
rollmean(serie, número de paços para cálculo, align = (“left”, “center”, “right”)).
Para o caso de calcular a média móvel para o futuro (proposta nossa), utilizaremos o “right”.

Vamos utilizar a mesma base de dados do prática anterior e aplicar a função:

# rollmean - função de zoo
# alinhamento "right" é para calcular para futuro
# left - calcula passado

demanda <- data.frame(dia = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14), 
                      demanda = c(78,65,90,71,80,101,84,60,87,80,102,91,95,112))

mm5 <- rollmean(demanda[,2], 5, align = "right")
# como demanda tem 2 colunas, tenho que indicar em qual será calculada a MM.
# Por isso demanda[,2]
# O valor 5 refere-se a quantidade de registros com o qual a MM será calculada.

mm5
##  [1] 76.8 81.4 85.2 79.2 82.4 82.4 82.6 84.0 91.0 96.0

Repare que mm5 tem apenas 10 observações, pois o primeiro cálculo é realizado com o valor das 5 demandas iniciais, dias 1 a 5.
Assim, temos que acrescentar os registros iniciais - quatro zeros.
Veja:

mm5 <- c(rep(0,4),mm5)

plot(demanda[,2], type='l',lwd=1)
lines(mm5, col=2, lwd= 3, lty=2)

8.6 Suavização Exponencial Simples (SES)


Esta técnica permite alterar os pesos das obserações mais recentes em relação as mais antigas.

É descrita matematicamente como:

\[ \bar Z_t = \alpha Z_t + \alpha (1 - \alpha) Z_{t-1} + \alpha(1-\alpha)^2 Z_{t-2} + ... \]


Ou seja, é uma média ponderada que dá peso às observações mais recentes, dependendo do valor de \(\alpha\).

8.6.1 Prática da Suavização Exponencial Simples SES


Utilizaremos a mesma base de dados da média móvel.

# Criando a base de dados para previsão
demanda <- data.frame(dia = seq(1,21), 
                      demanda = c(78,65,90,71,80,101,84,60,87,80,102,91,95,112,0,0,0,0,0,0,0),
                      media_exp = c(78,65,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
                      prev = rep(0,21) )

alpha <- 0.8

for(i in 4:21){
  demanda$media_exp[i] <- 
       (ifelse(demanda$demanda[i-1]!=0, 
               alpha * demanda$demanda[i-1], 
               alpha * demanda$media_exp[i-1])) + 
       (ifelse(demanda$demanda[i-2]!=0, 
               alpha * (1-alpha) * demanda$demanda[i-2], 
               alpha * (1-alpha) * demanda$media_exp[i-2])) +
       (ifelse(demanda$demanda[i-3]!=0,
               alpha * (1-alpha)^2 * demanda$demanda[i-3],
               alpha * (1-alpha)^2 * demanda$media_exp[i-3]))
}

demanda$prev[c(15:21)] <- demanda$media_exp[c(14:20)]

kable(demanda, digits = 2, format = "simple")
dia demanda media_exp prev
1 78 78.00 0.00
2 65 65.00 0.00
3 90 90.00 0.00
4 71 84.90 0.00
5 80 73.28 0.00
6 101 78.24 0.00
7 84 95.87 0.00
8 60 85.92 0.00
9 87 64.67 0.00
10 80 81.89 0.00
11 102 79.84 0.00
12 91 97.18 0.00
13 95 91.68 0.00
14 112 93.82 0.00
15 0 107.71 93.82
16 0 107.13 107.71
17 0 106.52 107.13
18 0 105.80 106.52
19 0 105.12 105.80
20 0 104.43 105.12
21 0 103.75 104.43

Vamos ao gráfico, visualizar o resultado.

plot(demanda$demanda[1:14], type='l', lwd=1, 
     xlim=c(1,17), ylim=c(60,120), 
     xlab = "Dias", ylab = "Demanda") 
  lines(demanda$media_exp, col=2, lwd=2, lty=2) 
  lines(demanda$prev,  col=3, lwd=3, lty=3)
  legend(1,120,
         c("Demanda", "Suavização - MExp", "Previsão"),
         lty = c(1, 2, 3),           # Line types
         col = c(1, 2, 3),           # Line colors
         lwd = c(1, 2, 3))

8.7 Séries temporais

Esta técnica cresce em quantidade e qualidade a medida que a digitalização da economia se expande. Ou seja, a disponibilização de grande quantidade de dados com qualidade proveniente de sensores diversos, coleta de dados informatizados e digitalização da gestão das organizações contribui para a eficiência desta técnica.
Podemos dizer que as séries temporais tentam extrair informações significativas a partir de dados organizados cronologicamente. Assim, ela pretende predizer comportamentos futuros a partir de dados históricos sobre o fenômeno estudado.
Atualmente, ela é aplicada em diversas áreas do conhecimento humano, destacando-se na medicina, meteorologia, economia e astronomia.

O R já dispõe de diversas bases de dados de séries temporais com as quais podemos entender os conceitos e praticar.

8.7.1 Bibliotecas

As bibliotecas básicas para utilização de séries temporais são:

library(forecast) # análises 
#library(fpp)
library(fpp2)     # coleção de séries
library(tseries)
library(patchwork) # análises graficas
library(mFilter)
library(xts)    
library(zoo)

8.7.2 Alguns conceitos importantes

Uma série temporal possui componentes básicos, a saber:

a. Tendência - padrão de crescimento (ou decrescimento) no tempo.
b. Sazonalidade - padrão periódico de repetição de um comportamento.
c. Ciclo - padrão que se repete em períodos aleatórios. Muitos autores e os modelos do R tratam os ciclos diluido nos outros componentes (principalmente a tendência).
d. Aleatoriedade ou ruído - componente aleatório que não se comporta como tendência, nem sazonalidade e nem ciclo.

De uma forma bem simples podemos representar a série como função de tendência, sazonalidade e ruído.

\(Sériestemporais = f(tendencia, sazonalidade, ruído)\)

Veja um exemplo:  A base de dados AirPassengers, nativa do R, representa os dados de totais mensais de passageiros de linhas aéreas internacionais, 1949 a 1960.
No R a função decompose decompõe a série temporal e a função autoplot faz o gráfico desses dados decompostos.

8.7.2.1 Modelos de decomposição aditivos e multiplicativos

Podemos utilizar dois tipos de modelos ao decompor uma série, o adititivo e o multiplicativo.

Modelos aditivo
O modelo aditivo é representado matemáticamente como:
\(Z_t = T_t + S_t + E_t\),
Onde \(Z_t\) representa o dado observado no período t.
\(T_t\) representa a componente de tendência.
\(S_t\) representa a componente sazonal.
\(E_t\) representa a parte não capturado do modelo, o ruído.

O modelo aditivo quando a decomposição não for proporcional à magnitude dos dados. Ou seja, a tendência e a sazonalidade não se alterarem com o tempo.

Modelos multiplicativo
O modelo multiplicativo é representado matemáticamente como:
\(Z_t = T_t . S_t . E_t\),
Onde \(Z_t\) representa o dado observado no período t.
\(T_t\) representa a componente de tendência.
\(S_t\) representa a componente sazonal.

\(E_t\) representa a parte não capturado do modelo, o ruído.
O modelo multiplicativo é apropriado quando o a variação do padrão sazonal ou tendência for proporcional à magnitude dos dados. É o caso típico da série AirPassenger visto acima, na qual existe uma tendência e a sazonalidade tem sua amplitude aumentada (fica mais intensa) com o passar do tempo.

Uma série ao ser decomposta com o comando decompose().

Para exemplificar utilizaremos a série elecequip disponível no pacote fpp. Essa séria representa o índice de pedidos de novos equipamentos eletônicos em 16 países da Europa.

data(elecequip)
plot(elecequip, xlab="Tempo", ylab="Índice de novas ordens" )

Vamos decompor essa série pelo modelo aditivo:

decomp <- decompose(elecequip, type = 'additive')
plot(decomp)

Caso queiramos retirar a sazonalidade da série devemos subtrair a decomposição sazonal da série inicial, isso seria:

ajuste_sazonal <- elecequip - decomp$seasonal
plot(ajuste_sazonal)

Caso queiramos retirar a tendência da série, devemos subtraí-la da série original.

ajuste_tend <- elecequip - decomp$trend
plot(ajuste_tend)

Quando subtraímos a tendência e a sazonalidade, fica somente a parte não capturada.

ajuste <- elecequip - decomp$trend - decomp$seasonal
plot(ajuste)

8.7.2.2 Previsão com função forecast()

A função forecast permite a previsão de uma série temporal e modelos lineares. Seus princiapis parâmetros são:

forecast(serie, h, level), onde:
serie - representa o objeto sobre o qual se fará a previsão.
h - representa o número de períodos a serem previstos.
level - representa o intervalo de confiança para a previsão.

Veja o exemplo:

forecast(AirPassengers, 7, 80)
##          Point Forecast    Lo 80    Hi 80
## Jan 1961       441.8018 419.6256 463.9780
## Feb 1961       434.1186 407.1668 461.0704
## Mar 1961       496.6300 460.6291 532.6310
## Apr 1961       483.2375 443.6210 522.8539
## May 1961       483.9914 440.0236 527.9591
## Jun 1961       551.0244 496.3368 605.7120
## Jul 1961       613.1797 547.3865 678.9728

Vamos representar graficamente essa previsão:

plot(forecast(AirPassengers, 7, 80))

8.7.2.3 Filtro de Hodrick-Prescott (HP)

Esse filtro é um método no qual se pretende estimar a tendência de longo prazo da série, deixando restar apenas as flutuações cíclicas.
Veja sua aplicação:

hp_filtro <- hpfilter(elecequip, type='lambda')
plot(hp_filtro)

8.7.2.4 Filtro de Holt Winters

O filtro de Holt Winters é um filtro que permite a identificação da tendência a partir da suaviazação exponencial simples (SES) ou por meio da suavização exponencial de Holt (SEH). Ela utiliza basicamente três parâmetros:
- alpha - \(\alpha\) - como parâmetro da suavização exponencial simples - este valor varia de 0 a 1 e quando próximo de 0 indica que as informações recentes explicam pouco os movimentos da série temporal e quando próximos de 1, explicam muito.
- beta - \(\beta\) - caso esse parâmetro seja configurado como falso a filtro irá realizar uma suavização exponencial simples (SES) caso contrário realizará a sauvização exponencial de Holt (SEH) que considera além do alpha este parâmtro que ajusta o nível de tendência.
- gama - \(\gamma\) - quando ajustado para TRUE, esse parâmetro captura a sazonalidade do modelo.
- seasonal - este parâmetro pode assumir os valores multiplicative ou additive para modelos multiplicativos ou aditivos.

8.7.2.4.1 Exemplos

Vamos realizar as previsões utilizando o modelo SEH, com sazonalidade aditiva e multiplicativa.

Modelo SEH
Quando os parâmetros não são ajustados, o modelo considera todos como verdadeiros.

ajuste <- HoltWinters(AirPassengers)
ajuste
## Holt-Winters exponential smoothing with trend and additive seasonal component.
## 
## Call:
## HoltWinters(x = AirPassengers)
## 
## Smoothing parameters:
##  alpha: 0.2479595
##  beta : 0.03453373
##  gamma: 1
## 
## Coefficients:
##           [,1]
## a   477.827781
## b     3.127627
## s1  -27.457685
## s2  -54.692464
## s3  -20.174608
## s4   12.919120
## s5   18.873607
## s6   75.294426
## s7  152.888368
## s8  134.613464
## s9   33.778349
## s10 -18.379060
## s11 -87.772408
## s12 -45.827781

Observe que os valores de:
Smoothing parameters:
alpha: 0.2479595
beta : 0.03453373
gamma: 1
São calculados automaticamente.

ajuste <- HoltWinters(AirPassengers)
prev <- forecast(ajuste, 7, level = 80)
print(prev)
##          Point Forecast    Lo 80    Hi 80
## Jan 1961       453.4977 437.0972 469.8983
## Feb 1961       429.3906 412.4590 446.3221
## Mar 1961       467.0361 449.5553 484.5169
## Apr 1961       503.2574 485.2097 521.3051
## May 1961       512.3395 493.7078 530.9713
## Jun 1961       571.8880 552.6556 591.1204
## Jul 1961       652.6095 632.7605 672.4586

Como o nível de confiança foi de 80% o modelo de previsão indica os valores superiores e inferiores da previsão. Veja o gráfico:

ajuste <- HoltWinters(AirPassengers, alpha = TRUE)
prev <- forecast(ajuste, 7, level = 80)
plot(prev)

Modelo SEH com beta

ajuste <- HoltWinters(AirPassengers, alpha = TRUE, beta = TRUE)
prev <- forecast(ajuste, 7, level = 80)
plot(prev)

Modelo SEH com beta e sazonalidade modelo aditivo

ajuste <- HoltWinters(AirPassengers, alpha = TRUE, beta = TRUE, gamma = TRUE, seasonal = "additive")
prev <- forecast(ajuste, 7, level = 80)
plot(prev)

Modelo SEH com beta e sazonalidade modelo multiplicativo

ajuste <- HoltWinters(AirPassengers, alpha = TRUE, beta = TRUE, gamma = TRUE, seasonal = "multiplicative")
prev <- forecast(ajuste, 7, level = 80)
plot(prev)

8.8 Regressão

É a técnica de dependência mais utilizada e versátil de todas. É aplicável em inúmeros casos variando dos casos mais genéricos aos mais específicos.
É um dos principais fundamentos para os modelos de previsão em negócios – de modelos econométricos aos modelos de desempenho de uma empresa em um mercado.
Quando a regressão é realizada com uma variável dependente e uma indempendente, é chamada de regressão simples. Quando a análise de regressão é feita com duas ou mais variáveis independentes é chamada de regressão múltipla.

BIBLIOTECAS:
library(dplyr) library(ggplot2) library(psych) library(corrplot) library(PerformanceAnalytics)

library(dplyr)
library(ggplot2)
library(psych)
library(corrplot)
## corrplot 0.95 loaded
library(PerformanceAnalytics)
## 
## Anexando pacote: 'PerformanceAnalytics'
## O seguinte objeto é mascarado por 'package:fpp3':
## 
##     prices
## O seguinte objeto é mascarado por 'package:graphics':
## 
##     legend

Carregar a base de dados mtcars

data(mtcars)

8.8.1 Analisando os dados

Para auxiliar a explicação dos modelos de regressão utilizaremos a base de dados mtcars , nativa do R.
Os dados dessa base foram extraídos da revista americana Motor Trend de 1974 e compreendem o consumo de combustível e 10 aspectos de design e desempenho de automóveis para 32 automóveis (modelos de 1973 a 1974).
Suas colunas são:
[, 1] mpg Miles/(US) gallon – milhas por galão
[, 2] cyl Number of cylinders – número de cilindros
[, 3] disp Displacement (cu.in.) - cilindrada
[, 4] hp Gross horse-power - HP
[, 5] drat Rear axle ratio - relação de câmbio
[, 6] wt Weight (1000 lbs) – peso em 1000 lbs
[, 7] qsec 1/4 mile time - aceleração
[, 8] vs Engine (0 = V-shaped, 1 = straight) – motor em V ou em linha
[, 9] am Transmission (0 = automatic, 1 = manual) - transmissão
[,10] gear Number of forward gears – número de marchas avante
[,11] carb Number of carburetors – número de carburadores

Atenção! Na base de dados mtcars todas as colunas contém dados numéricos e não existem dados perdidos (NA) facilitando a análise e evitando a geraração de erros oriundos de dados não numéricos.
Bases de dados com NA e colunas não numéricas podem exigir análises diferentes.

glimpse(mtcars)
## Rows: 32
## Columns: 11
## $ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8,…
## $ cyl  <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8,…
## $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 16…
## $ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180…
## $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92,…
## $ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3.…
## $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 18…
## $ vs   <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,…
## $ am   <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,…
## $ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3,…
## $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2,…
summary(mtcars)
##       mpg             cyl             disp             hp       
##  Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
##  1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
##  Median :19.20   Median :6.000   Median :196.3   Median :123.0  
##  Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
##  3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
##  Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  
##       drat             wt             qsec             vs        
##  Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  
##  1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  
##  Median :3.695   Median :3.325   Median :17.71   Median :0.0000  
##  Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  
##  3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  
##  Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  
##        am              gear            carb      
##  Min.   :0.0000   Min.   :3.000   Min.   :1.000  
##  1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  
##  Median :0.0000   Median :4.000   Median :2.000  
##  Mean   :0.4062   Mean   :3.688   Mean   :2.812  
##  3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  
##  Max.   :1.0000   Max.   :5.000   Max.   :8.000

8.8.1.1 Anallisando as correlações

A correlação é realizada utilizando-se o comando cor, cor(mtcars) – cria a matriz de correlação entre as variáveis de mtcars. No exemplo abaixo é utilizado o comando round para apresentar apenas duas casas decimais.

round(cor(mtcars), 2)
##        mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
## mpg   1.00 -0.85 -0.85 -0.78  0.68 -0.87  0.42  0.66  0.60  0.48 -0.55
## cyl  -0.85  1.00  0.90  0.83 -0.70  0.78 -0.59 -0.81 -0.52 -0.49  0.53
## disp -0.85  0.90  1.00  0.79 -0.71  0.89 -0.43 -0.71 -0.59 -0.56  0.39
## hp   -0.78  0.83  0.79  1.00 -0.45  0.66 -0.71 -0.72 -0.24 -0.13  0.75
## drat  0.68 -0.70 -0.71 -0.45  1.00 -0.71  0.09  0.44  0.71  0.70 -0.09
## wt   -0.87  0.78  0.89  0.66 -0.71  1.00 -0.17 -0.55 -0.69 -0.58  0.43
## qsec  0.42 -0.59 -0.43 -0.71  0.09 -0.17  1.00  0.74 -0.23 -0.21 -0.66
## vs    0.66 -0.81 -0.71 -0.72  0.44 -0.55  0.74  1.00  0.17  0.21 -0.57
## am    0.60 -0.52 -0.59 -0.24  0.71 -0.69 -0.23  0.17  1.00  0.79  0.06
## gear  0.48 -0.49 -0.56 -0.13  0.70 -0.58 -0.21  0.21  0.79  1.00  0.27
## carb -0.55  0.53  0.39  0.75 -0.09  0.43 -0.66 -0.57  0.06  0.27  1.00

Como essa matriz pode ser consultada e utilizada várias vezes, sugere-se criar uma variável com esse resultado

mat_corr <- cor(mtcars) 

O comando cor só é executado com dados numéricos, assim, caso existam colunas não numéricas haverá erro.

Coeficiente de correlação (r) Coeficiente que indica a força da associação entre quaisquer duas variáveis métricas.
O sinal (+ ou –) indica a direção da relação.
O valor pode variar de –1 a +1, onde +1 indica uma perfeita relação positiva, 0 indica relação nenhuma, e –1, uma perfeita relação negativa ou reversa (quando uma variável se torna maior, a outra fica menor).

A library(corrplot) facilita a análise das correlações. Veja os exemplos:

corrplot(mat_corr, method = "circle")

corrplot(mat_corr, method = "color")

corrplot(mat_corr, method = "number")

corrplot(mat_corr, method = "ellipse")

corrplot(mat_corr, method = "circle", type = "upper")

corrplot(mat_corr, method = "number", type = "lower")

corrplot(mat_corr, method="color",  type="upper",
         addCoef.col = "black", insig = "blank", diag=FALSE )

A library(PerformanceAnalytics) também oferece gráficos muito elucidativos:

chart.Correlation(mtcars, pch=19)

8.8.1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1

8.8.2 Regressão simples

Consite em uma variável independente explicando uma dependente. No caso da base mtcars, podemos tentar explicar o consumo pelo peso. O modelo ficaria:

plot(mtcars$mpg ~ mtcars$wt)

Para realizar essa regressão utilizamos o comando:

modelo_simples <- lm(mpg ~ wt, data = mtcars)

summary(modelo_simples)
## 
## Call:
## lm(formula = mpg ~ wt, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.5432 -2.3647 -0.1252  1.4096  6.8727 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)  37.2851     1.8776  19.858 < 0.0000000000000002 ***
## wt           -5.3445     0.5591  -9.559       0.000000000129 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.046 on 30 degrees of freedom
## Multiple R-squared:  0.7528, Adjusted R-squared:  0.7446 
## F-statistic: 91.38 on 1 and 30 DF,  p-value: 0.0000000001294

Podemos representar esse modelo graficamente:

plot(lm(mpg ~ wt, data = mtcars))

Passaremos a explicar cada uma das variáveis que permitem a interpretação do modelo na regressã múltipla.

8.8.3 Regressão linear múltipla

Tecnica estatística geral usada para analisar a relação entre uma única variável dependente e diversas independentes (preditoras).
Quando as variáveis não são métricas, devem ser transformadas em relações binárias (1/0).

A técnica consiste em usar as variáveis independentes (cujos valores são conhecidos) para prever o valor da variável dependente escolhida.
Cada variável independente é ponderada pelo procedimento da análise de regressão para garantir a melhor previsão possível, a partir do conjunto de variáveis independentes.
Quando existem diversas variáveis independents, os pesos dos seus coeficientes demonstram a contribuição proporcional de cada variável independente que contribui para explicar sua influência na variável dependente.
O conjunto delas forma a variável estatística de regressão ou equação de regressão.

8.8.3.1 Conceitos importantes

Vamos utilizar um modelo de regressão linear múltipla para explicar alguns conceitos importantes, em seguida, passaremos a explicar como se ajusta um modelo (uma equação de regressão linear).

O modelo a ser analisado é:

modelo_mult <- lm(mpg ~ wt + hp + qsec + drat, data = mtcars)

Nele, tentamos explicar o consumo, representado pela variável dependente “mpg” (milhas por galão) com as variáveis independentes “wt” (peso do veículo), “hp” (cavalos de potência), “qsec” (tempo de quarto de milha) e “drat” (relação do eixo traseiro).

A função summary() nos fornece uma visão detalhada dos resultados do modelo, incluindo os coeficientes estimados para cada variável independente, estatísticas de ajuste (como o R-quadrado, que mede a proporção da variância explicada pelo modelo) e p-valores que indicam a significância estatística dos coeficientes estimados.

summary(modelo_mult)
## 
## Call:
## lm(formula = mpg ~ wt + hp + qsec + drat, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.5775 -1.6626 -0.3417  1.1317  5.4422 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 19.25970   10.31545   1.867 0.072785 .  
## wt          -3.70773    0.88227  -4.202 0.000259 ***
## hp          -0.01784    0.01476  -1.209 0.237319    
## qsec         0.52754    0.43285   1.219 0.233470    
## drat         1.65710    1.21697   1.362 0.184561    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.539 on 27 degrees of freedom
## Multiple R-squared:  0.8454, Adjusted R-squared:  0.8225 
## F-statistic: 36.91 on 4 and 27 DF,  p-value: 0.0000000001408

Intercepto (Intercept)
O intercepto tem valor interpretativo somente quando zero é um valor conceitualmente válido para a variável independente (i.e., a variável independente pode ter um valor nulo e ainda manter sua relevância prática).
Por exemplo, considere que a variável independente é dólares para anúncios. Se for realista que, em algumas situações, nenhum anúncio é feito, então o intercepto representará o valor da variável dependente quando anúncio é nulo.
Se o valor independente representa uma medida que jamais pode ter um valor verdadeiro de zero (p.ex., atitudes ou percepções), o intercepto auxilia no melhoramento do processo de previsão, mas sem valor explanatório. (HAIR, p. 158)

Coeficiente de regressão
A variação estimada na variável dependente por variação unitária da variável independente.
Se o coeficiente de regressão é percebido como estatisticamente significante (ou seja, o coeficiente é significativamente diferente de zero), o valor do coeficiente de regressão indica a extensão na qual a variável independente se associa com a dependente.

p-valores Os p-valores associados aos coeficientes estimados são usados para testar a hipótese nula de que o coeficiente é igual a zero.
Valores de p baixos (geralmente abaixo de 0,05) indicam que o coeficiente é estatisticamente significativo, ou seja, há evidências estatísticas para rejeitar a hipótese nula e concluir que a variável independente tem um efeito significativo na variável dependente.
“.”, um, dois o três astericos representam esse grau de significância.

Coeficiente de determinação (R2) Medida da proporção da variância da variável dependente em torno de sua média que é explicada pelas variáveis independentes ou preditoras.

O coeficiente pode variar entre 0 e 1.

Se o modelo de regressão é propriamente aplicado e estimado, o pesquisador pode assumir que quanto maior o valor de R2, maior o poder de explicação da equação de regressão e, portanto, melhor a previsão da variável dependente. (HAIR, p. 152)

Coeficiente ajustado de determinação (R2 ajustado) - Adjusted R2-saquared
Medida modificada do coeficiente de determinação que considera o número de variáveis independentes incluídas na equação de regressão e o tamanho da amostra.
Apesar de a adição de variáveis independentes sempre fazer com que o coeficiente de determinação aumente, o coeficiente ajustado de determinação pode cair se as variáveis independentes acrescentadas tiverem pouco poder de explicação e/ou se os graus de liberdade se tornarem muito pequenos.
Essa estatística é muito útil para comparação entre equações com diferentes números de variáveis independentes, diferentes tamanhos de amostras, ou ambos.

Erro de previsão
Diferença entre os valores reais e os previstos da variável dependente, para cada observação na amostra - resíduo.

Resíduo (e) Erro na previsão de nossos dados da amostra nomeado como \(\epsilon\).
Raramente nossas previsões serão perfeitas. Consideramos que o erro aleatório ocorrerá, mas assumimos que esse erro é uma estimativa do verdadeiro erro aleatório na população, não apenas o erro na previsão de nossa amostra (e). Consideramos que o erro na população que estamos estimando é distribuído com uma média de 0 e uma variância constante (homoscedástica). (HAIR, p. 153)

Avaliação da precisão de previsão Se a soma de quadrados dos erros (SSE) representa uma medida de nossos erros de previsão, também devemos conseguir determinar uma medida de nosso sucesso de previsão, o qual podemos chamar de soma de quadrados da regressão (SSR).
Juntas, essas duas medidas devem igualar a soma total de quadrados (SST), o mesmo valor de nossa previsão de referência.
Como o pesquisador acrescenta variáveis independentes, a soma total de quadrados agora pode ser dividida em (1) a soma de quadrados prevista pela(s) variável(eis) independente(s), que é a soma de quadrados da regressão (SSR), e (2) a soma de quadrados dos erros (SSE): Erros da regressão

Soma total de quadrados = Soma de erros quadrados + Soma de quadrados de regressão onde (HAIR, p. 159):

estimadores da regressão
estimadores da regressão

Avaliação da precisão de previsão Utilizando outra nomenclatura:
TSS (SST ou SST) - Soma total dos quadrados (total sum of squares)
EES (EES ou EES)- soma dos quadrados dos erros (error sum of squares) - uma medida de nossos erros de previsão
RSS (EER ou EER) - soma dos quadrados da regressão (regression sum of squares)
Assim:
Erros da regressão E o R2 é:

Erros da regressão
Erros da regressão

Os resíduos podem ser analisados utilizando gráficos de diagnóstico, como o gráfico de resíduos versus valores ajustados e o gráfico de normalidade dos resíduos, conforme mostrado abaixo:

Gráfico de resíduos versus valores ajustados

plot(modelo_mult, which = 1)

E o gráfico de normalidade dos resíduos

plot(modelo_mult, which = 2) 

Para um modelo ser considerado bem ajustado, os resíduos devem ter algumas características:

Linearidade do fenômeno
Relação linear entre variáveis independentes e dependente (gráfico (a), próximo slide). Caso essa linearidade não exista (gráfico (b)), existem técnicas para fazer ocorrer.

Variância constante do termo de erro (homoscedasticidade)
Também é representadas pelo gráfico (a). A sua não ocorrência, a heterocedasticidade, é representadas nos gráficos (c) e (d). Essa característica é testada pelo teste Levene para homogeneidade da variância.

Independência dos termos de erro
Assumimos em regressão que cada valor previsto é independente, o que significa que o valor previsto não está relacionado com qualquer outra previsão; ou seja, eles não são sequenciados por qualquer variável. Resíduos independentes, sugerem o gráfico nulo (gráfico (a)).

Normalidade da distribuição dos termos de erro
É testada por meio de um histograma dos resíduos (gráfico (g)).
A análise visual dos resíduos é uma boa técnica para avaliar se as características acima estão contempladas no modelos. Veja nos gráficos abaixo como o que caracteriza a falta de cada uma dessas características.
Os gráficos (a) e (g) representam como os resíduos devem se comportar num modelo ajustado.

Diagnóstico dos resíduos
Diagnóstico dos resíduos

8.8.3.2 Modelo de estimação STEPWISE

Existem algumas técnicas para se ajustar o modelo de regressão linear múltipla, um delos é o STEPWISE, que passaremos a explicar.
  Passaremos a explicar esse modelo.

1. Começar com o modelo de regressão simples, selecionando a variável independente que é a mais fortemente correlacionada com a variável dependente. A equação seria: \(Y = b_0 + b_1X_1\).

2. Examinar os coeficientes de correlação parcial para encontrar uma variável independente adicional que explique a maior parte estatisticamente significante da variância não explicada (erro) remanescente da primeira equação de regressão.
3. Recalcular a equação de regressão usando as duas variáveis independentes e examinar o valor parcial F para a variável original no modelo para ver se esta ainda faz uma contribuição significante, dada a presença da nova variável independente. Se não for o caso, eliminar a variável. A eliminação de variáveis no modelo diferencia o modelo stepwise dos modelos de adição forward/eliminação backward. Se a variável original ainda fizer uma contribuição significante, a equação será \(Y = b_0 + b_1X_1 + b_2X_2\).
4. Continuar esse procedimento examinando todas as variáveis independentes não-presentes no modelo para determinar se alguma faria uma adição estatisticamente significante para a equação corrente e, assim, deveria ser incluída em uma equação revisada. Se uma nova variável independente é incluída, examinar todas as variáveis independentes previamente no modelo para julgar se elas devem ser mantidas.
5. Continuar adicionando variáveis independentes até que nenhuma das candidatas remanescentes para inclusão possa contribuir em melhora estatisticamente significante na precisão preditiva. Esse ponto acontece quando todos os coeficientes de regressão parcial remanescentes são não-significantes.
Vamos a um exemplo:

Primeiro passo
Identificamos a variável com maior correlção com a variável dependente, no caso wt.

modelo <- lm(mpg ~ wt, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.5432 -2.3647 -0.1252  1.4096  6.8727 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)  37.2851     1.8776  19.858 < 0.0000000000000002 ***
## wt           -5.3445     0.5591  -9.559       0.000000000129 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.046 on 30 degrees of freedom
## Multiple R-squared:  0.7528, Adjusted R-squared:  0.7446 
## F-statistic: 91.38 on 1 and 30 DF,  p-value: 0.0000000001294

Segundo passo
Reavaliamos as correlações para incluir uma nova variável - a que se segue em correlação com a variável dependente.

Terceiro passo
Recalculamos o modelo e verificando significancias:

modelo <- lm(mpg ~ wt + cyl, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.2893 -1.5512 -0.4684  1.5743  6.1004 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)  39.6863     1.7150  23.141 < 0.0000000000000002 ***
## wt           -3.1910     0.7569  -4.216             0.000222 ***
## cyl          -1.5078     0.4147  -3.636             0.001064 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.568 on 29 degrees of freedom
## Multiple R-squared:  0.8302, Adjusted R-squared:  0.8185 
## F-statistic: 70.91 on 2 and 29 DF,  p-value: 0.000000000006809

Quarto passo
Examinamos as correlações para incluir uma nova variável

Quinto passo
Recalculamos e verificaamos significância e contribuição para o modelo

modelo <- lm(mpg ~ wt + cyl + disp, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + disp, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.4035 -1.4028 -0.4955  1.3387  6.0722 
## 
## Coefficients:
##              Estimate Std. Error t value           Pr(>|t|)    
## (Intercept) 41.107678   2.842426  14.462 0.0000000000000162 ***
## wt          -3.635677   1.040138  -3.495            0.00160 ** 
## cyl         -1.784944   0.607110  -2.940            0.00651 ** 
## disp         0.007473   0.011845   0.631            0.53322    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.595 on 28 degrees of freedom
## Multiple R-squared:  0.8326, Adjusted R-squared:  0.8147 
## F-statistic: 46.42 on 3 and 28 DF,  p-value: 0.00000000005399

No caso, a variável não foi mantida no modelo.

Sexto passo
Buscamos uma nova variável independente - hp

Sétimo passo
Recalculamos o modelo

modelo <- lm(mpg ~ wt + cyl + hp, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + hp, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.9290 -1.5598 -0.5311  1.1850  5.8986 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept) 38.75179    1.78686  21.687 < 0.0000000000000002 ***
## wt          -3.16697    0.74058  -4.276             0.000199 ***
## cyl         -0.94162    0.55092  -1.709             0.098480 .  
## hp          -0.01804    0.01188  -1.519             0.140015    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.512 on 28 degrees of freedom
## Multiple R-squared:  0.8431, Adjusted R-squared:  0.8263 
## F-statistic: 50.17 on 3 and 28 DF,  p-value: 0.00000000002184

Oitavo passo
Buscamos uma nova variável independente - drat

Nono passo
Recalculamos o modelo com drat

modelo <- lm(mpg ~ wt + cyl + drat, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + drat, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.2944 -1.5576 -0.4667  1.5678  6.1014 
## 
## Coefficients:
##             Estimate Std. Error t value   Pr(>|t|)    
## (Intercept)  39.7677     6.8729   5.786 0.00000326 ***
## wt           -3.1947     0.8293  -3.852   0.000624 ***
## cyl          -1.5096     0.4464  -3.382   0.002142 ** 
## drat         -0.0162     1.3231  -0.012   0.990317    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.613 on 28 degrees of freedom
## Multiple R-squared:  0.8302, Adjusted R-squared:  0.812 
## F-statistic: 45.64 on 3 and 28 DF,  p-value: 0.00000000006569

Décimo passo Buscamos uma nova variável independente - vs

Décimo primeiro passo Recalculamos o modelo com vs

modelo <- lm(mpg ~ wt + cyl + vs, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + vs, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.3115 -1.7450 -0.3759  1.5174  6.0433 
## 
## Coefficients:
##             Estimate Std. Error t value         Pr(>|t|)    
## (Intercept)  38.7461     3.3989  11.399 0.00000000000495 ***
## wt           -3.2464     0.7879  -4.120         0.000304 ***
## cyl          -1.3641     0.6135  -2.223         0.034433 *  
## vs            0.5242     1.6271   0.322         0.749734    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.608 on 28 degrees of freedom
## Multiple R-squared:  0.8309, Adjusted R-squared:  0.8127 
## F-statistic: 45.85 on 3 and 28 DF,  p-value: 0.0000000000624

Décimo segundo passo
Buscamos uma nova variável independente - am

Décimo terceiro passo
Recalculamos o modelo com am

modelo <- lm(mpg ~ wt + cyl + am, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + am, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.1735 -1.5340 -0.5386  1.5864  6.0812 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)  39.4179     2.6415  14.923 0.00000000000000742 ***
## wt           -3.1251     0.9109  -3.431             0.00189 ** 
## cyl          -1.5102     0.4223  -3.576             0.00129 ** 
## am            0.1765     1.3045   0.135             0.89334    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.612 on 28 degrees of freedom
## Multiple R-squared:  0.8303, Adjusted R-squared:  0.8122 
## F-statistic: 45.68 on 3 and 28 DF,  p-value: 0.0000000000651

Décimo quarto passo
Buscamos uma nova variável independente - carb

Décimo quinto passo
Recalculamos o modelo com carb

modelo <- lm(mpg ~ wt + cyl + carb, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + carb, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.6692 -1.5668 -0.4254  1.2567  5.7404 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)  39.6021     1.6823  23.541 < 0.0000000000000002 ***
## wt           -3.1595     0.7423  -4.256             0.000211 ***
## cyl          -1.2898     0.4326  -2.981             0.005880 ** 
## carb         -0.4858     0.3295  -1.474             0.151536    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.517 on 28 degrees of freedom
## Multiple R-squared:  0.8425, Adjusted R-squared:  0.8256 
## F-statistic: 49.91 on 3 and 28 DF,  p-value: 0.00000000002322

Décimo sexto passo
Buscamos uma nova variável independente - qsec

Décimo sétimo passo
Recalculamos o modelo com qsec

modelo <- lm(mpg ~ wt + cyl + qsec, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl + qsec, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.5937 -1.5621 -0.3595  1.2097  5.5500 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  29.4291     8.1912   3.593 0.001238 ** 
## wt           -3.8616     0.9138  -4.226 0.000229 ***
## cyl          -0.9277     0.6113  -1.518 0.140280    
## qsec          0.4945     0.3863   1.280 0.211061    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.54 on 28 degrees of freedom
## Multiple R-squared:  0.8396, Adjusted R-squared:  0.8224 
## F-statistic: 48.86 on 3 and 28 DF,  p-value: 0.00000000002979

8.8.3.3 MODELO AJUSTADO

O modelo ajustado é:

modelo <- lm(mpg ~ wt + cyl, data = mtcars)
summary(modelo)
## 
## Call:
## lm(formula = mpg ~ wt + cyl, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.2893 -1.5512 -0.4684  1.5743  6.1004 
## 
## Coefficients:
##             Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)  39.6863     1.7150  23.141 < 0.0000000000000002 ***
## wt           -3.1910     0.7569  -4.216             0.000222 ***
## cyl          -1.5078     0.4147  -3.636             0.001064 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.568 on 29 degrees of freedom
## Multiple R-squared:  0.8302, Adjusted R-squared:  0.8185 
## F-statistic: 70.91 on 2 and 29 DF,  p-value: 0.000000000006809
plot(modelo, which = 1) 

plot(modelo, which = 2) 

hist(modelo$residuals)

A análise acima ajusta um modelo de regressão linear múltipla com a variável dependente “mpg” (milhas por galão) e as variáveis independentes “wt” (peso do veículo), “hp” (cavalos de potência), “qsec” (tempo de quarto de milha) e “drat” (relação do eixo traseiro).

Essa análise de regressão linear múltipla nos fornece informações valiosas sobre o relacionamento entre as variáveis independentes e a variável dependente, bem como a qualidade do ajuste do modelo aos dados.
É importante interpretar cuidadosamente os resultados e considerar a adequação do modelo aos objetivos da regressão.

Após o ajuste do model é possível realizar previsões com dados não existentes.

8.8.3.4 Previsão

Vamos supor que queremos fabricar um carro com as seguintes características: mpg = ? quero saber o consumo cyl 8 - número de cilindros disp 360 - cilindrada hp 250 - HP drat 2.7 - relação de câmbio wt 2.30 - peso em 1000 lbs qsec 15 - aceleração vs 0 = motor em V am 0 = automatic - transmissão gear 5 - número de marchas avante carb 2 - número de carburadores

Na verdade, para previsão do consumo, importa somente:

novos_dados <- data.frame( wt = 2.3, 
                           cyl = 8)

A partir de então utilizamos a seguinte função para previsão:

previsoes <- predict(modelo, newdata = novos_dados)
previsoes
##        1 
## 20.28467

8.9 Redes neuronais

Existem vários pacotes para aplicação de inteligência artificial no R. Vamos explicar alguns deles.

8.9.1 neuralnet - fazendo previsões

Serão utilizados dados de ações na bolsa de valores para apresentar as funcionalidades de neuronet.

Carregando as bibliotecas:

library(zoo)
library(data.table)
library(dplyr)
library(naivebayes)
library(neuralnet)
library(quantmod)
library(zoo)
library(forecast)
#library(DMwR2)
library(stats)
library(plogr)
library(ggplot2)
library(psych)

8.9.1.1 Padronizando dados

A padronização pode ser realizada de diversas formas. Foi criada uma função para padronizar e despadronizar os dados, mas existem funções prontas para isso, entre elas a scale para padronização e unscale para a despadronização.
A padronização consiste em subtrair de cada caso a média de todos os casos e dividir pelo desvio padrão.

## Padronização 
PadronizacaoEstatisticaDados <- function(vetorDados){
  # Valida dados
  if(!is.numeric(vetorDados)){
    stop("Dados não são numéricos!")
  }
  # Padroniza dados
  dadosPadronizados <- (vetorDados - mean(vetorDados, na.rm = TRUE)) / sd(vetorDados, na.rm = TRUE)
  # Retorno da funcao
  return(dadosPadronizados)
}   

# Despadronização
DesPadronizacao <- function(vetorDados, media_orig, desvpad_orig){
  # Valida dados
  if(!is.numeric(vetorDados)){
    stop("Dados não são numéricos!")
  }
  # DesPadroniza dados
  dadosDesPadronizados <- vetorDados * desvpad_orig + media_orig
  # Retorno da funcao
  return(dadosDesPadronizados)
}   

8.9.1.2 Obtendo os dados

A função getSymbols extrai dados das cotações diretamente da internet. Esses dados serão utilizados para o treniamento da rede e, em seguida a avaliação da previsão.
Ao utilizarmos essa função os dados retornam em formato _.xts.

# Estes dados são para treinamento da rede
getSymbols("IBM", src='yahoo', from='2014-01-01', to='2017-12-31')
## [1] "IBM"
# Renomeando as colunas para facilitar manuseio
names(IBM) <- c("open", "high", "low", "close", "volume", "adjusted")

# Transformando os dados em data.frame com nome dat_a
dat_a = data.frame(IBM)
head(dat_a)
##                open     high      low    close  volume adjusted
## 2014-01-02 178.9771 179.1587 177.0555 177.3709 4755639 109.0489
## 2014-01-03 177.6577 179.1109 177.1510 178.4321 4250107 109.7014
## 2014-01-06 178.9197 179.1205 177.1510 177.8203 4254919 109.3252
## 2014-01-07 178.1931 181.9790 178.1836 181.3671 6205186 111.5058
## 2014-01-08 181.0038 181.0899 179.0249 179.7036 4815470 110.4831
## 2014-01-09 180.7075 181.1664 178.3461 179.1396 4520080 110.1363

8.9.1.3 Analisando dados

A correlação de pearson é a mais utilizada para avaliação preliminar de correlações.

pairs.panels(dat_a, method = 'pearson') 

# pairs.panels(dat_a, method = 'spearman')
# pairs.panels(dat_a, method = 'kendall')

8.9.1.4 Definindo a variável dependente

O exemplo irá prever o valor de fechamento em função das outras variáveis, por isso, essa variável será deslocada em um dia, ou seja, avaliaremos o fechamento no dia posterior as demais vaariáveis. Para isso, será criada uma variável chamada closem1.
A função Lag realiza essa defazagem.

dat_a['closem1'] <- as.numeric(Lag(Cl(IBM),1))

# Preencho os NA existentes na tabela - também poderíamos eliminar
dat_a <- na.fill(dat_a,"extend")
head(dat_a)
##          open     high      low    close  volume adjusted  closem1
## [1,] 178.9771 179.1587 177.0555 177.3709 4755639 109.0489 177.3709
## [2,] 177.6577 179.1109 177.1510 178.4321 4250107 109.7014 177.3709
## [3,] 178.9197 179.1205 177.1510 177.8203 4254919 109.3252 178.4321
## [4,] 178.1931 181.9790 178.1836 181.3671 6205186 111.5058 177.8203
## [5,] 181.0038 181.0899 179.0249 179.7036 4815470 110.4831 181.3671
## [6,] 180.7075 181.1664 178.3461 179.1396 4520080 110.1363 179.7036

8.9.1.5 Normalizando os dados

É necessário que eles estejam na mesma escala para entrada no modelo.

# Cada coluna será normalizada
dat_scale_a <- matrix(0, nrow = dim(dat_a)[1], ncol = dim(dat_a)[2])
colnames(dat_scale_a) <- c("open", "high", "low", "close", "volume", "adjusted", "closem1")
dat_scale_a[,1] <- PadronizacaoEstatisticaDados(dat_a[,1])
dat_scale_a[,2] <- PadronizacaoEstatisticaDados(dat_a[,2])
dat_scale_a[,3] <- PadronizacaoEstatisticaDados(dat_a[,3])
dat_scale_a[,4] <- PadronizacaoEstatisticaDados(dat_a[,4])
dat_scale_a[,5] <- PadronizacaoEstatisticaDados(dat_a[,5])
dat_scale_a[,6] <- PadronizacaoEstatisticaDados(dat_a[,6])
dat_scale_a[,7] <- PadronizacaoEstatisticaDados(dat_a[,7])

head(dat_scale_a)
##          open     high      low    close       volume  adjusted  closem1
## [1,] 1.516890 1.461286 1.459469 1.415364  0.105502154 0.9224837 1.412243
## [2,] 1.435677 1.458348 1.465351 1.480637 -0.105455294 0.9942697 1.412243
## [3,] 1.513359 1.458935 1.465351 1.443002 -0.103447257 0.9528795 1.477458
## [4,] 1.468633 1.634562 1.528886 1.661167  0.710395091 1.1927951 1.439856
## [5,] 1.641654 1.579935 1.580654 1.558847  0.130469506 1.0802727 1.657829
## [6,] 1.623410 1.584635 1.538887 1.524152  0.007203875 1.0421192 1.555599

8.9.1.6 Construindo o modelo

nn_a <- neuralnet(closem1 ~ open + high + low + close + volume + adjusted,
                data = dat_scale_a, hidden  = c(5,5), threshold = 1, stepmax = 1000)

# print(nn_a)
8.9.1.6.1 Plotando o modelo

O comando para fazer o gráfico do modelo é muito simples, veja:

plot(nn_a)
Modelo de redes neuronais com função neuralnet
Modelo de redes neuronais com função neuralnet

8.9.1.7 Fazendo a previsão

prev_a <- predict(nn_a, dat_scale_a)
head(prev_a, 3)
##          [,1]
## [1,] 1.465350
## [2,] 1.474828
## [3,] 1.467858

8.9.1.8 Fazendo a desnormalização da previsão

# prev = unscale(prev, dat_scale) # não funcionou com o DMwR
prev_a = DesPadronizacao(prev_a, mean(dat_a[,'close']), sd(dat_a[,'close']))
head(prev_a, 3)
##          [,1]
## [1,] 178.1836
## [2,] 178.3377
## [3,] 178.2244
mean(prev_a)
## [1] 154.3655
sd(prev_a)
## [1] 16.16848
plot(as.vector(Cl(IBM)), type = 'l')
lines(prev_a, col='red')

#accuracy(as.vector(prev_a), Cl(IBM))

8.9.1.9 Fazendo a previsão - previsão dia-a-dia

# Estes dados são para testar a rede - com 1 ano de diferença
getSymbols("IBM", src='yahoo', from='2018-01-01', to='2019-12-31')
## [1] "IBM"
names(IBM) <- c("open", "high", "low", "close", "volume", "adjusted")

dat_t = data.frame(IBM)
# Vou prever o fechamento, então devo deslocar um dia
dat_t['closem1'] <- as.numeric(Lag(Cl(IBM),1))

# Preencho os NA existentes na tabela - também poderíamos eliminar
dat_t <- na.fill(dat_t,"extend")
head(dat_t, 3)
##          open     high      low    close  volume adjusted  closem1
## [1,] 147.7056 148.0019 146.7878 147.4665 4395815 103.4128 147.4665
## [2,] 150.4207 152.7820 149.4551 151.5201 9875914 106.2554 147.4665
## [3,] 152.6291 155.1816 152.3614 154.5889 7903785 108.4075 151.5201
# Normalizando os dados - é necessário que eles estejam na mesma escala
dat_scale_t <- matrix(0, nrow = dim(dat_t)[1], ncol = dim(dat_t)[2])
colnames(dat_scale_t) <- c("open", "high", "low", "close", "volume", "adjusted", "closem1")
dat_scale_t[,1] <- PadronizacaoEstatisticaDados(dat_t[,1])
dat_scale_t[,2] <- PadronizacaoEstatisticaDados(dat_t[,2])
dat_scale_t[,3] <- PadronizacaoEstatisticaDados(dat_t[,3])
dat_scale_t[,4] <- PadronizacaoEstatisticaDados(dat_t[,4])
dat_scale_t[,5] <- PadronizacaoEstatisticaDados(dat_t[,5])
dat_scale_t[,6] <- PadronizacaoEstatisticaDados(dat_t[,6])
dat_scale_t[,7] <- PadronizacaoEstatisticaDados(dat_t[,7])

# Realizando a previsão com a base teste, de 502 linhas
prev_t <- predict(nn_a, dat_scale_t)

# Testando a previsão realizada
prev_t = DesPadronizacao(prev_t, mean(dat_t[,'close']), sd(dat_t[,'close']))
head(prev_t, 3)
##          [,1]
## [1,] 147.0568
## [2,] 152.1767
## [3,] 153.8660
mean(prev_t)
## [1] 134.3491
sd(prev_t)
## [1] 10.37599
plot(as.vector(Cl(IBM)), type = 'l')
lines(prev_t, col='red')

#accuracy(as.vector(prev_t), Cl(IBM))

8.9.2 naivebayes - identificando elementos

Este pacote permite que façamos a identificação de grupos e a partir disso, é possível reconhecer um elemento (registro) a partir de suas características.
No nosso exemplo, utilizaremos a base de dados iris que possui as características de 3 plantas. Então, o modelo recohecerá os tipos de plantas, setosa, versicolor e virginica a partir do treinamento que teve.

Para utilizar o pacote é necessário que a variável dependente seja categórica (factor), que neste caso, é o tipo de planta.
As demais variáveis são as medidas das pétalas e da sépala (parte externa da flor que envolve as pétalas, normalmente verde).
Veja os dados.

data("iris")
dados_ia <- iris
summary(dados_ia)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
# Para utilizar o pacote é necessário uma variável categórica (factor)
#########################################################
# Realizando a primeira avaliação dos dados
str(dados_ia)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# Uma segunda análise para saber quantas variáveis por especies
xtabs(~Species, data=dados_ia)
## Species
##     setosa versicolor  virginica 
##         50         50         50

A análise de correlação é utilizada para verificar se como as variáveis se comportam entre si e, principalmente em relação a variável dependente, no caso, as species.

# A correlação de pearson é a mais utilizada (padrão)
pairs.panels(dados_ia, method = 'pearson') 

# A partir daqui, verificamos que as correlações são fortes
# e que esta base de dados é muito boa para fazer agrupamentos

Depois de reconhecidos os dados, vamos à construção do modelo. Ele mostra que para o conjunto de registros (linhas) da base de dados, existe a mesma quantidade de cada tipo, por isso a probabilidade a priori é igual para as espécies (A priori probabilities), 33,3%.
O modelo também define a média e desvio padrão para cada variável, considerando as espécies.

# CRIANDO O MODELO
modelo <- naive_bayes(Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width, data = dados_ia )

modelo
## 
## ================================= Naive Bayes ==================================
## 
## Call:
## naive_bayes.formula(formula = Species ~ Sepal.Length + Sepal.Width + 
##     Petal.Length + Petal.Width, data = dados_ia)
## 
## -------------------------------------------------------------------------------- 
##  
## Laplace smoothing: 0
## 
## -------------------------------------------------------------------------------- 
##  
## A priori probabilities: 
## 
##     setosa versicolor  virginica 
##  0.3333333  0.3333333  0.3333333 
## 
## -------------------------------------------------------------------------------- 
##  
## Tables: 
## 
## -------------------------------------------------------------------------------- 
## :: Sepal.Length (Gaussian) 
## -------------------------------------------------------------------------------- 
##             
## Sepal.Length    setosa versicolor virginica
##         mean 5.0060000  5.9360000 6.5880000
##         sd   0.3524897  0.5161711 0.6358796
## 
## -------------------------------------------------------------------------------- 
## :: Sepal.Width (Gaussian) 
## -------------------------------------------------------------------------------- 
##            
## Sepal.Width    setosa versicolor virginica
##        mean 3.4280000  2.7700000 2.9740000
##        sd   0.3790644  0.3137983 0.3224966
## 
## -------------------------------------------------------------------------------- 
## :: Petal.Length (Gaussian) 
## -------------------------------------------------------------------------------- 
##             
## Petal.Length    setosa versicolor virginica
##         mean 1.4620000  4.2600000 5.5520000
##         sd   0.1736640  0.4699110 0.5518947
## 
## -------------------------------------------------------------------------------- 
## :: Petal.Width (Gaussian) 
## -------------------------------------------------------------------------------- 
##            
## Petal.Width    setosa versicolor virginica
##        mean 0.2460000  1.3260000 2.0260000
##        sd   0.1053856  0.1977527 0.2746501
## 
## --------------------------------------------------------------------------------

Repare que as curvas do modelo representam as curvas de densidade das características das sépalas e pétalas.
Veja os gráficos.

plot(modelo)

Passamos então a predizer qual a espécie a partir de suas características. No caso, pegamos o registro 3, aleatóriamente, para identificar a probabilidade da espécie a que pertence a partir de suas características.
Entendam que essa é uma situação acadêmica para explicar como funciona a utilização da função e não se pretende explicar o modelo.

tabela <- dados_ia[3,]
calculo <- predict(modelo, tabela, type = 'prob')
(round(head(calculo), 2))
##      setosa versicolor virginica
## [1,]      1          0         0

Ao apresentar o valor 1 para setosa, o modelo sugere que as características daquele registro são de setosa, o que é confirmado conforme vemos as características do registro, abaixo.

dados_ia[3,]
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 3          4.7         3.2          1.3         0.2  setosa

Da mesma forma como o modelo acertou, existe a possibilidade de erro, por isso passaremos a testar o modelo em todos os registros de cada espécie e identificar a probabilidade de acerto.

Atenção! Normalmente, dividimos a base de dados em registros para treinamento e teste do modelo para verificar sua acurácia.

Veja para versicolor.

# probabilidade de versicolor
tabela <- dados_ia %>% 
  select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) %>%
  filter(Species == "versicolor") %>%
  select(-c(Species))

# registros iniciais da tabela que será testada.
head(tabela,3)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1          7.0         3.2          4.7         1.4
## 2          6.4         3.2          4.5         1.5
## 3          6.9         3.1          4.9         1.5
# Cálculos efetuados.
calculo <- predict(modelo, tabela, type = 'prob')
(round(head(calculo, 3),2))
##      setosa versicolor virginica
## [1,]      0       0.80      0.20
## [2,]      0       0.94      0.06
## [3,]      0       0.46      0.54
(round(tail(calculo, 3),2))
##       setosa versicolor virginica
## [48,]      0          1         0
## [49,]      0          1         0
## [50,]      0          1         0

Veja para setosa.

# probabilidade de setosa
tabela <- dados_ia %>% 
  select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) %>%
  filter(Species == "setosa") %>%
  select(-c(Species))

calculo <- predict(modelo, tabela, type = 'prob')
(round(head(calculo), 2))
##      setosa versicolor virginica
## [1,]      1          0         0
## [2,]      1          0         0
## [3,]      1          0         0
## [4,]      1          0         0
## [5,]      1          0         0
## [6,]      1          0         0
summary(calculo)
##      setosa    versicolor                    virginica                         
##  Min.   :1   Min.   :0.00000000000000000   Min.   :0.000000000000000000000000  
##  1st Qu.:1   1st Qu.:0.00000000000000000   1st Qu.:0.000000000000000000000000  
##  Median :1   Median :0.00000000000000002   Median :0.000000000000000000000001  
##  Mean   :1   Mean   :0.00000000000281227   Mean   :0.000000000000000000094423  
##  3rd Qu.:1   3rd Qu.:0.00000000000000035   3rd Qu.:0.000000000000000000000011  
##  Max.   :1   Max.   :0.00000000010764747   Max.   :0.000000000000000003721344

E agora, virginica.

# probabilidade de virginica
tabela <- dados_ia %>% 
  select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) %>%
  filter(Species == "virginica")

# registros iniciais da tabela que será testada.
head(tabela,3)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
## 1          6.3         3.3          6.0         2.5 virginica
## 2          5.8         2.7          5.1         1.9 virginica
## 3          7.1         3.0          5.9         2.1 virginica
calculo <- predict(modelo, tabela, type = 'prob')
(round(head(calculo, 3),2))
##      setosa versicolor virginica
## [1,]      0       0.00      1.00
## [2,]      0       0.03      0.97
## [3,]      0       0.00      1.00
(round(tail(calculo, 3),2))
##       setosa versicolor virginica
## [48,]      0       0.00      1.00
## [49,]      0       0.00      1.00
## [50,]      0       0.06      0.94