1  Introdução ao R/RStudio

A leitura desta seção é fundamental para compreender a base computacional deste material. Utilizamos o ambiente R/RStudio em todas as análises aqui apresentadas.

Ainda que existam alternativas no mercado como Python, SPSS, julia, Jamovi, Excel, etc. A escolha pelo R para o ensino de Estatística (especialmente a Espacial) é deliberada. Além de ser um software gratuito, de código livre (open source) e criado para computação estatística e gráfica, o R destaca-se pela vasta biblioteca de pacotes dedicados à fronteira do conhecimento científico.

NotaFontes e Referências

A elaboração deste conteúdo é fruto da prática do autor, alicerçada na literatura fundamental da comunidade R. Recomendamos a leitura complementar das seguintes obras base: Paradis (2005), Venables, Smith, e R Core Team (2015), Wickham, Çetinkaya-Rundel, e Grolemund (2023), Wickham (2016) e Wickham (2019), entre outras.

1.1 O Ecossistema R vs RStudio

Uma distinção fundamental para quem está começando:

  • R: é uma linguagem de programação e um ambiente de software livre usado para analisar dados, criar gráficos e aplicar métodos estatísticos. Foi criado por Ross Ihaka e Robert Gentleman na Universidade de Auckland, Nova Zelândia, em 1993, inspirado na linguagem S. Hoje, é muito utilizado por estatísticos, cientistas de dados e pesquisadores em várias áreas, contando com uma grande comunidade que desenvolve pacotes e amplia suas funcionalidades.

  • RStudio: é um programa que facilita o uso do R. Ele oferece uma interface gráfica amigável, onde o usuário pode escrever e executar códigos, visualizar gráficos, organizar arquivos e acompanhar os objetos criados durante a análise. É um Ambiente de Desenvolvimento Integrado (IDE), ou seja, um espaço que reúne várias ferramentas para programar de forma mais prática e organizada. O RStudio foi desenvolvido pela empresa RStudio, PBC (atualmente Posit Software, PBC), fundada por Joseph J. Allaire, e teve sua primeira versão lançada em 2011.

DicaSaiba mais

Clique aqui para ver o vídeo produzido pela \(C^2\) Conexão Ciência. Para mais informações sobre R, Clique aqui.

O RStudio divide-se em quatro painéis principais que você deve conhecer (Figura 1.1):

  1. Source Editor (Editor de Fonte): Onde você escreve seus scripts (.R) e relatórios em Rmarkdown (.Rmd) ou Quarto (.qmd). É aqui que o código é salvo.

  2. Console: Onde o código é executado interativamente e os resultados de texto aparecem imediatamente.

  3. Environment (Ambiente): Mostra todos os objetos (dados, variáveis, funções) carregados na memória RAM (Workspace).

  4. Files/Plots/Help: Área multifuncional para gerenciamento de arquivos, visualização de gráficos e consulta de documentação.

Figura 1.1: Página de download do R no CRAN.

1.2 Instalação do R/Rstudio

Para usar o RStudio, você deve primeiro instalar o R.

Passo 1: Instalar o R

  1. Acesse o site oficial do R: Clique aqui e assista ao vídeo colocado no final destas instruções.
  2. Escolha o link de download para o seu sistema operacional (Linux, MacOS ou Windows) (veja a Figura 1.2, onde seleciono Windows porque é meu sistema operacional. Se não conhece o seu sistema operacional, veja o vídeo do Ativando o Saber: Clique aqui. Se em algum lugar aparecer Windows, então você usa Windows).
  3. Clique em base (ou na versão mais recente recomendada) para baixar o instalador principal.
  4. Execute o arquivo baixado e siga as instruções, mantendo as configurações padrão.

Assista ao vídeo 1 da Professora Fernanda Peres: Clique aqui para ver o vídeo.

Figura 1.2: Página de download do R no CRAN.

Passo 2: Instalar o RStudio

  1. Visite a página de download do RStudio: Clique aqui.
  2. A versão gratuita “RStudio Desktop” é a recomendada para iniciantes. Clique no botão de download (a Figura 1.3 mostra isso e o vídeo contém o tutorial).
  3. O site geralmente detecta seu sistema operacional e sugere o instalador correto. Baixe-o.
  4. Execute o instalador e siga as instruções, mantendo as opções padrão.
Figura 1.3: Página de download do RStudio.
Nota

Assim que instalar o R e o RStudio, sempre que quiser fazer análises, use o RStudio clicando nele duas vezes. Se não encontrar o RStudio na área de trabalho, pesquise por Rstu em uma das opções abaixo (1 ou 2) mostradas na Figura 1.4.

Figura 1.4: Encontrar aplicativo que sumiu.

1.3 Atalhos de teclado essenciais

  • Ctrl+Enter (no sistema operacional Windows) / Cmd+Enter (no Mac): Executa a linha de código atual.
  • Alt+-: Insere o operador de atribuição (<-).
  • Ctrl+Shift+M: Insere o operador Pipe (%>% ou |>).
NotaPipe (%>% ou |>)

O Pipe transfere o resultado da expressão à esquerda para ser o primeiro argumento da função à direita, transformando a difícil leitura matemática aninhada \(f(g(x))\) em uma sequência linear lógica \(x \to g \to f\). Ele é fundamental para a higiene do código, permitindo ler o script como uma receita (“pegue os dados, e então filtre, e então calcule”), eliminando o excesso de parênteses e variáveis temporárias.

  • Sem Pipe (Leitura: de dentro para fora, propenso a erro): localize a função central (subset) para filtrar os dados, depois expanda o olhar para calcular a média (mean) desse resultado, e finalmente olhe para as extremidades para aplicar o arredondamento (round) com o argumento 2 que está longe do início.
Código
round(mean(subset(dados, valor > 10)$valor, na.rm = TRUE), 2)
  • Com Pipe (Leitura Lógica: da esquerda para a direita): Pegue os dados, e então filtre onde valor > 10, e então calcule a média, e então arredonde o resultado final para 2 casas, seguindo a ordem lógica e cronológica da execução.
Código
dados |> 
  subset(valor > 10) |> 
  mean(na.rm = TRUE) |> 
  round(2)
  • Esc: Interrompe um comando que está demorando muito ou travou.
  • Ctrl+Shift+F10: Reinicia a sessão do R (limpa a memória RAM).
  • Ctrl + Shift + C: Comentar/ignorar algo no Windows/Linux
  • Cmd + Shift + C: Comentar/ignorar algo no Mac
Dica

Além de Ctrl + Shift + C ou Cmd + Shift + C, você também pode usar o caractere # para instruir o R a ignorar completamente tudo o que estiver escrito à direita dele na mesma linha. Isso serve para deixar anotações para você mesmo (ou outros programadores) sem interferir na execução do código.

Código
x <- 10
# x <- 20  <-- Esta linha não vai rodar, o valor continua 10.
y <- x + 5

A Filosofia do objeto

No R, você raramente verá uma tela cheia de resultados imediatos após uma análise complexa. O R opera salvando resultados em objetos. Se você roda uma regressão linear, o resultado não é apenas um texto impresso, mas um objeto complexo que pode ser consultado, manipulado e usado como entrada para outras funções posteriormente.

1.4 Fundamentos da linguagem R

Antes de algoritmos complexos, você precisa entender como o R processa informações básicas.

1.4.1 Ajuda e Documentação

O R possui um sistema de documentação robusto integrado. Aprenda a pedir ajuda:

  • help(topic): Abre a documentação completa e técnica sobre o tópico especificado. Exemplo, se você quiser saber o que a função str() faz, faça help(str)
Código
help(str) 
  • ?topic: Um atalho rápido para o comando acima (ex: ?mean).
Código
?str 
  • help.search("termo") ou ??termo: Pesquisa o termo em todo o sistema de ajuda (títulos e descrições), útil quando você não sabe o nome exato da função (ex: ??regression).
Código
help.search("str")
  • apropos("termo"): Retorna uma lista com os nomes de todos os objetos e funções disponíveis no ambiente atual que contêm o termo (ex: apropos("test")).
Código
apropos("str") #descomente
  • help.start(): Inicia a versão HTML completa da ajuda no seu navegador padrão.
Código
help.start() #descomente

1.4.2 Operadores e Atribuição

Atribuição

ImportanteAtenção: O R é case-sensitive

O R diferencia letras maiúsculas de minúsculas. Isso vale para nomes de funções, variáveis e também para caminhos de arquivos e pastas no seu computador.

  • <-: Atribuição à esquerda. É a convenção padrão e histórica do R. Cria uma variável. Se eu quisesse criar um objeto de nome “Alex”, recebendo número 4, temos:
Código
Alex <- 4
  • =: Atribuição à esquerda. Funciona, mas é preferível usar apenas para definir argumentos dentro de funções.
Código
Alex = 4
  • <<-: Superatribuição. Atribui um valor a uma variável no ambiente pai (global), geralmente usado dentro de funções avançadas para alterar variáveis externas.
Código
total <- 100 # Variável definida no ambiente global

# Função com atribuição normal (<-)
teste_local <- function() {
  total <- 50  # Cria uma nova variável LOCAL chamada 'total'. A global continua 100.
}

# Função com superatribuição (<<-)
teste_global <- function() {
  total <<- 50 # Altera a variável 'total' que já existe lá fora.
}

# Executando:
teste_local()
print(total) # Resultado: 100 (não mudou)
[1] 100
Código
teste_global()
print(total) # Resultado: 50 (foi alterada pela superatribuição)
[1] 50

Operações Aritméticas * +, -, *, /: Soma, Subtração, Multiplicação e Divisão.

Código
2 + 4  # Soma
[1] 6
Código
2 - 4  # Subtração
[1] -2
Código
2 * 4  # Multiplicação
[1] 8
Código
2 / 4  # Divisão
[1] 0.5
  • ^ ou **: Exponenciação (potência).
Nota

^ é o mais comum no R, mas ** também funciona).

Código
2 ^ 3  # 2 elevado a 3 = 2x2x2= 8
[1] 8
  • %%: Módulo (Resto da divisão). Útil para verificar paridade ou ciclos.
Código
5 %% 2  # Retorna 1 (pois 5 dividido por 2 dá 2 e sobra 1)
[1] 1
  • %/%: Divisão inteira (Quociente). Descarta a parte decimal.
Código
5 %/% 2 # Retorna 2 (a parte inteira da divisão)
[1] 2
ImportanteExecução de uma operação

Se você executar uma operação sem atribuí-la a um objeto (usando <- ou =), o R apenas imprime o resultado no console e o descarta imediatamente. Ele não fica salvo na memória.

  • Exemplo: Ao rodar apenas 2 + 4, você vê 6 na tela, mas não consegue usar esse 6 em contas futuras. Solução: use sempre nome_do_objeto_da_sua_preferência <- 2 + 4

  • Sobrescrita de Variáveis: O R não guarda o histórico de uma variável. Se você atribuir um novo valor a um objeto que já existe, o valor antigo é apagado e substituído pelo novo (a última operação prevalece).

Código
b <- 10      # 'b' vale 10
b <- 2 + 4   # Agora 'b' vale 6. O 10 foi perdido.

Lógica e Comparação

Resultam sempre em TRUE ou FALSE. * ==, !=: Igualdade exata e Diferença.

Código
10 == 10  # TRUE (10 é igual a 10)
[1] TRUE
Código
10 != 10  # FALSE (10 não é diferente de 10)
[1] FALSE
Código
"R" == "Python" # FALSE
[1] FALSE
  • <, >, <=, >=: Menor, Maior, Menor ou igual, Maior ou igual.
Código
5 > 3    # TRUE
[1] TRUE
Código
5 <= 2   # FALSE
[1] FALSE
Código
x <- 10
x >= 10  # TRUE
[1] TRUE
  • !: Negação (NÃO). Inverte o valor lógico (!TRUE é FALSE).
Código
!TRUE         # Retorna FALSE
[1] FALSE
Código
!(5 > 3)      # 5 > 3 é TRUE, logo a negação retorna FALSE
[1] FALSE
Código
is.na(4)      # Verifica se é Nulo (FALSE)
[1] FALSE
Código
!is.na(4)     # "Não é nulo" (TRUE)
[1] TRUE
  • &, |: “E” / “OU” vetorizados. Comparam elemento por elemento de dois vetores.
Código
v1 <- c(TRUE, TRUE, FALSE)
v2 <- c(FALSE, TRUE, FALSE)

v1 & v2  # Retorna: FALSE TRUE FALSE (Apenas a 2ª posição tem TRUE nos dois)
[1] FALSE  TRUE FALSE
Código
v1 | v2  # Retorna: TRUE TRUE FALSE (Basta um ser TRUE)
[1]  TRUE  TRUE FALSE
  • &&, ||: “E” / “OU” de controle. Avaliam apenas o primeiro elemento.
Código
x <- 10
y <- 3
divisao_inteira <- x %/% y
resto <- x %% y
logica <- (x > 5) & (y < 5) # TRUE E TRUE = TRUE

Usados exclusivamente em estruturas de controle como if.

Código
tem_saldo <- TRUE
conta_ativa <- TRUE

if (tem_saldo && conta_ativa) {
  print("Compra aprovada")
}
[1] "Compra aprovada"

1.4.3 Vetores

Não existem escalares (números soltos) no R. Um número sozinho é, na verdade, um vetor de comprimento 1. Saiba mais sobre vetores clicando aqui

Criação

  • c(...): Função “combine” ou “concatenate”. Junta elementos num mesmo vetor.
Código
números <- c(10, 20, 30) # Vetor numérico

nomes <- c("Ana", "Beto", "Carla") # Vetor de texto

misturado <- c(10, "Ana") # Resultado: "10", "Ana" (Tudo vira texto)
Nota

O c é Minúsculo

  • from:to: Gera uma sequência de inteiros (ex: 1:10).
Código
1:5   # Retorna: 1 2 3 4 5
[1] 1 2 3 4 5
Código
5:1   # Retorna: 5 4 3 2 1
[1] 5 4 3 2 1
  • seq(from, to, by, length): Gera sequências complexas. Permite definir o passo (by) ou o tamanho final desejado (length).
Código
# Sequência de 0 a 10, pulando de 2 em 2
seq(from = 0, to = 10, by = 2) # Resultado: 0 2 4 6 8 10
[1]  0  2  4  6  8 10
Código
# Quero exatos 5 números entre 0 e 10
seq(from = 0, to = 10, length.out = 5)# Resultado: 0.0  2.5  5.0  7.5  10.0
[1]  0.0  2.5  5.0  7.5 10.0
  • rep(x, times, each): Replica elementos. times repete o vetor todo; each repete cada elemento individualmente.
Código
vetor <- c(1, 2)

rep(vetor, times = 3) # Resulta em: 1, 2, 1, 2, 1, 2
[1] 1 2 1 2 1 2
Código
rep(vetor, each = 3) # Resulta em:  1, 1, 1, 2, 2, 2
[1] 1 1 1 2 2 2
  • %in%: Verifica se um valor está dentro de um vetor e retornaTRUEouFALSE`
Código
1 %in% vetor  # 1 está dentro do objeto vetor?
[1] TRUE
Código
c()
NULL

A Regra da reciclagem

O superpoder do R é a vetorização. Se você tentar operar dois vetores de tamanhos diferentes, o R “recicla” (repete) o vetor menor até que ele tenha o tamanho do maior.

Código
valores <- c(10, 20, 30, 40)
pesos <- c(1, 2) 

resultado <- valores * pesos # O que acontece internamente: 10*1, 20*2, 30*1, 40*2
print(resultado)
[1] 10 40 30 80

1.4.4 Tipos e/ou valores especiais e coerção

O R possui termos específicos para lidar com exceções matemáticas e dados faltantes. É crucial saber diferenciá-los.

  • NA: Not Available. Representa um dado ausente ou desconhecido. O NA é “contagioso”. A maioria das operações matemáticas envolvendo um NA resultará em NA (pois não se pode somar algo a um valor desconhecido).
Importante

Nunca use == para testar se algo é NA (ex: x == NA retorna NA, e não TRUE ou FALSE). Use sempre a função is.na().

Código
vetor <- c(1, 2, NA, 4)
mean(vetor)      # Retorna NA (a média de dados desconhecidos é desconhecida)
[1] NA
Código
is.na(vetor)     # Retorna: FALSE FALSE TRUE FALSE
[1] FALSE FALSE  TRUE FALSE
  • NaN: Not a Number. Resultado de uma indeterminação matemática. Ocorre quando o cálculo é impossível de ser definido numericamente. Resultado de indeterminações matemáticas (ex: 0/0).
Código
0 / 0  # Retorna NaN
[1] NaN
  • Inf: Infinito (ex: 1/0).
Código
10 / 0   # Retorna Inf
[1] Inf
Código
-5 / 0   # Retorna -Inf
[1] -Inf
  • NULL: Vazio. Representa a ausência total de conteúdo. Diferente do NA (que é um “espaço reservado para um dado que falta”), o NULL significa que a estrutura ou vetor nem sequer existe naquele ponto. É muito usado para apagar elementos de listas.
Código
x <- NULL  # O objeto x existe, mas é vazio (tamanho 0).
c(1, 2, NULL, 3) # Resultado: 1, 2, 3 (O NULL é ignorado na concatenação)
[1] 1 2 3

1.4.5 Funções de conversão e verificação

No R, é fundamental saber qual é o tipo do objeto (classe) com o qual você está lidando. Estas famílias de funções permitem testar ou alterar esses tipos.

Funções as... (Conversão / Coerção Explícita)

Estas funções tentam forçar a transformação de um objeto de um tipo para outro.

  • as.numeric(), as.character(), as.logical(), as.factor(): Forçam a conversão de um tipo para outro.
Código
# Convertendo Número para Texto
as.character(123) # Resultado: "123" (Note as aspas)
[1] "123"
Código
# Convertendo Texto para Número
as.numeric("10.5") # Resultado: 10.5
[1] 10.5
Código
as.numeric("Bola") # Resultado: NA ("NAs introduzidos por coerção")
[1] NA
Dica

Uma técnica muito comum é converter TRUE e FALSE em números para fazer contagens. TRUE vira 1 e FALSE vira 0.

Código
as.numeric(TRUE)  # Retorna 1
[1] 1
Código
as.numeric(FALSE) # Retorna 0
[1] 0

Funções is... (Verificação / Teste lógico)

Estas funções fazem uma pergunta ao objeto e retornam sempre TRUE ou FALSE. São ideais para usar dentro de condicionais (if).

  • is.numeric(), is.character(), etc.: Verificam se o objeto é do tipo especificado.
Código
x <- 10
y <- "10"

is.numeric(x)    # TRUE (É um número)
[1] TRUE
Código
is.numeric(y)    # FALSE (É um texto, apesar de conter dígitos)
[1] FALSE
Código
is.character(y)  # TRUE
[1] TRUE

1.5 Gerenciamento de diretórios e objetos

Saber onde o R está salvando seus arquivos (diretório de trabalho) e como limpar a memória é essencial para a organização.

Diretório de trabalho

É a pasta no seu computador onde o R irá ler e salvar arquivos (como .csv ou .xlsx) por padrão.

  • getwd() (Get Working Directory): Descobre em qual pasta você está trabalhando agora.
Código
getwd() # Exemplo de saída: /home/almonha/curso-de-verao-notas-de-aulas"
  • setwd() (Set Working Directory): Muda o diretório de trabalho para outra pasta.
Código
setwd("C:/Users/Alex/Curso_verao")
ImportanteUse setwd() com cautela

Se usarsetwd("C:/Users/SeuNome/..."), seu código não será reprodutível. Se você enviar esse script para outra pessoa, o código quebrará, pois o computador dele não tem a pasta “SeuNome”, isto é, usam diretórios diferentes.

A solução profissional é trabalhar com R Projects (.Rproj).

Criação de projeto

  1. No RStudio: File > New Project > New Directory.
  2. Isso cria uma raiz autocontida.
  3. Utilize o pacote here para referenciar arquivos. Ele encontra automaticamente a raiz do projeto, independente de qual subpasta você esteja. Isto é, se rodar o código:
Código
dados <- read.csv(here("dados", "tabela.csv"))

, o computador entende: Na raiz do projeto, entre na pasta dados, leia tabela.csv, ou seja, esta é a forma ideal e universal de ler arquivos.

AvisoCuidado com barras

No Windows, o caminho copiado usa contrabarra (\), mas no R você deve usar barra normal (/) ou barra dupla (\\).

  • Forma correta (Barra normal ou dupla):
Código
setwd("C:/Users/SeuNome/Projetos/Analise_Dados")
  • Forma incorreta (Vai dar erro no Windows)
Código
setwd("C:\Users\SeuNome\Projetos\Analise_Dados")

Gerenciando objetos na memória

Conforme você cria variáveis (x, y, dados), elas ocupam a memória RAM (o Environment).

  • ls() (Listar): Mostra os nomes de todos os objetos criados no ambiente atual.
Código
ls()
  • rm() (Remover): Apaga objetos da memória para liberar espaço ou evitar confusão.
Código
rm(nome_do_objeto_a_remover)
  • Limpeza total (O comando “Vassoura”): Para apagar tudo o que está na memória e começar do zero (muito comum no início de scripts) use rm(list = ls())
Código
rm(list = ls())
  • gc(): (Garbage Collection) Força o sistema a liberar memória RAM que não está mais sendo usada. Essencial ao trabalhar com Big Data.
Código
gc()
  • Limpeza de de nomes das colunas de objetos: Nomes de colunas com espaços, acentos ou caracteres especiais (Média (kg), Ano/Mês) exigem o uso de crases irritantes no código. Limpe-os imediatamente.
Código
if (!require("pacman")) install.packages("pacman")
pacman::p_load(tidyverse, janitor,flextable)

df_sujo <- data.frame(
  'Nome do Aluno' = c("Ana", "Beto"),
  'NOTA FINAL' = c(9, 8),
  check.names = FALSE
)

df_limpo <- df_sujo %>%
  janitor::clean_names() # Transforma tudo em: nome_do_aluno, nota_final
names(df_limpo)
[1] "nome_do_aluno" "nota_final"   

1.6 Pacotes: Leitura e instalação

O R base vem apenas com as funcionalidades essenciais. Para fazer análises avançadas, precisamos instalar pacotes (conjuntos de funções extras criadas pela comunidade). Pense no R como um celular novo: ele vem com funções de fábrica (ligar, agenda), mas para usar o Instagram ou WhatsApp, você precisa instalar os Apps (Pacotes).

Instalação (install.packages)

Você faz isso apenas uma vez por computador (como baixar o App da loja).

Código
install.packages("tidyverse")
install.packages("ggplot2")
Dica

Note que o nome do pacote deve estar entre aspas

Carregamento (library(.) ou require(.))

Você deve fazer isso toda vez que abrir o RStudio ou iniciar uma nova sessão (como abrir o App para usar). Note que aqui não precisa de aspas.

Código
library(tidyverse)
Nota

Coloque todos os library() ou require() necessários nas primeiras linhas do seu script.

DicaUse pacman e p_load

Para evitar deixar seu script cheio de install.packages(".") e library(.) , onde . é pacote, use o código abaixo comando que permite instalar e carregar os pacotes simultaneamente.

Código
# O comando que segue diz: se não carregar o pacote pacman instale-o
if (!require("pacman")) install.packages("pacman")
#O comando abaixo instala os pacotes se não estão instalados e carrega-os
pacman::p_load(tidyverse, flextable)

1.7 Estruturas de dados

Além de vetores, o R organiza dados em estruturas mais complexas.

Indexação e Seleção (Subsetting)

No R, utilizamos colchetes [ ] para acessar, extrair ou modificar pedaços específicos dos dados.

Vetores:

Código
x <- c(10, 20, 30, 40, 50)
names(x) <- c("Ana", "Beto", "Carla", "Davi", "Eva")
  • x[n]: Seleciona o elemento na posição n.
Código
x[2]  # Retorna 20 (o segundo elemento)
Beto 
  20 
  • x[-n]: Seleciona tudo exceto o elemento na posição n.
Código
x[-2] # Retorna: 10, 30, 40, 50 (O 20 foi removido)
  Ana Carla  Davi   Eva 
   10    30    40    50 
  • x[1:n]: Seleciona uma sequência de posições.
Código
x[2:4] # Retorna: 20, 30, 40 (Da 2ª à 4ª posição)
 Beto Carla  Davi 
   20    30    40 
  • x[c(1,4)]: Seleciona posições específicas não sequenciais.
Código
x[c(1, 5)] # Retorna: 10, 50 (O primeiro e o último)
Ana Eva 
 10  50 
  • x[x > 3]: Seleção lógica (filtro). Retorna elementos que satisfazem a condição (TRUE). Isto é, O R testa cada elemento. Onde for TRUE, ele mantém; onde for FALSE, ele descarta.
Código
x[x > 30] # Resultado: 40, 50
Davi  Eva 
  40   50 
  • x["nome"]: Seleciona pelo nome, se o vetor tiver o atributo names.
Código
x["Carla"]      # Retorna 30
Carla 
   30 
Código
x[c("Ana", "Eva")] # Retorna 10 e 50
Ana Eva 
 10  50 

Listas: Diferente dos vetores (que só aceitam um tipo de dado), as listas são a estrutura mais flexível do R. Elas podem conter qualquer coisa: números, textos, vetores, data frames e até outras listas.

Código
aluno <- list(
  nome = "Mariana",
  notas = c(9.5, 8.0, 7.5),
  ativo = TRUE
)
  • lista[n]: Retorna uma nova lista contendo apenas o elemento n. (Pense: pega a gaveta inteira).
Código
x <- aluno[2]
# O que é 'x'? É uma LISTA contendo as notas.
class(x) # Resultado: "list"
[1] "list"
  • lista[[n]]: Extrai o conteúdo do objeto na posição n. (Pense: tira o objeto da gaveta).
Código
y <- aluno[[2]]
# O que é 'y'? É um VETOR numérico (as notas em si).
class(y) # Resultado: "numeric"
[1] "numeric"
Código
mean(y)  # Funciona (média das notas).
[1] 8.333333
Código
# mean(x) daria erro, pois não se calcula média de uma "lista".
  • lista$nome: É a forma mais comum e legível de usar o [[...]]. Extrai o conteúdo diretamente usando o nome atribuído ao elemento.
Código
aluno$nome   # Retorna: "Mariana"
[1] "Mariana"
Código
aluno$notas  # Retorna: 9.5 8.0 7.5
[1] 9.5 8.0 7.5

Matrizes e Data Frames

Diferente dos vetores, aqui lidamos com duas dimensões. A regra de ouro no R é sempre: [ LINHA , COLUNA ].

Código
dados <- data.frame(
  Nome = c("Ana", "Beto", "Carla"),
  Idade = c(22, 30, 25),
  Nota = c(8, 7, 9)
)
  • df[i, j]: Elemento na linha i, coluna j.
Código
dados[1, 2] # Linha 1 ("Ana"), Coluna 2 ("Idade") -> Retorna 22
[1] 22
  • df[i, ]: Seleciona toda a linha i.
Código
dados[2, ]# Retorna todos os dados do "Beto"
  • df[, j]: Seleciona toda a coluna j.
Código
dados[, 2]# Retorna o vetor: 22 30 25
[1] 22 30 25
  • df$coluna: Seleciona a coluna pelo nome (específico para Data Frames e Listas). Note que este não funciona em matrizes.
Código
dados$Nome  #seleciona a coluna "Nome"

Matrizes e Arrays

  1. Matrizes

Matrizes são vetores com duas dimensões (linhas e colunas). Todos os dados devem ser do mesmo tipo (ex: tudo numérico).

  • matrix(data, nrow, ncol): Cria a matriz de nrow linhas e ncol colunas. O preenchimento padrão é por coluna. Use byrow=TRUE para preencher por linha.
Código
M <- matrix(1:6, nrow = 2, ncol = 3, byrow = TRUE);M
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
  • t(x): Transposta (inverte linhas por colunas).
Código
M_t <- t(M);M_t
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6
  • %*%: O operador para multiplicação matricial real (diferente de * que multiplica elemento por elemento).
Código
M_mult <- M %*% M_t; M_mult
     [,1] [,2]
[1,]   14   32
[2,]   32   77
  • solve(A, b): Resolve sistemas lineares \(Ax = b\). Se b for omitido, inverte a matriz A.
Código
A <- matrix(c(4, 2, 7, 6), nrow = 2)
A_inv <- solve(A) # Inversa de A
Código
#SISTEMA DE EQUAÇÕES: Ax=b
# 3x + 2y = 5
# 1x + 4y = 10
A <- matrix(c(3, 1, 2, 4), nrow = 2)
b <- c(5, 10)

#RESOLVENDO-O
resultado_x <- solve(A, b)
print(resultado_x) 
[1] 0.0 2.5
  1. Arrays

Enquanto matrizes são estritamente bidimensionais (linhas e colunas), arrays são estruturas de dados n-dimensionais. Pense em um array 3D como um cubo de dados ou uma pilha de matrizes. Eles são fundamentais em estatística espacial (x, y, tempo) ou em imagens (x, y, canais de cor).

  • array(data, dim): O argumento dim é um vetor que define o tamanho de cada dimensão c(linhas, colunas, profundidade/camadas, ...).
Código
# Imagine que são dados de temperatura de 2 cidades, em 3 meses, por 2 anos.
meu_array <- array(data = 1:12, dim = c(2, 3, 2))

print(meu_array)
, , 1

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

, , 2

     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12
Código
dim(meu_array) # Retorna 2 3 2
[1] 2 3 2

Data Frames

É a estrutura mais importante para Ciência de Dados. Pense nele como uma planilha de Excel: colunas podem ter tipos diferentes (texto, números, datas), mas todas devem ter o mesmo comprimento (número de linhas) ( Tabela 1.1).

  • data.frame(...): Cria um data frame manualmente.
Código
pacman::p_load(gt)

df <- data.frame(
  id = 1:3,
  nome = c("Ana", "Beto", "Carla"),
  nota = c(8.5, 9.0, 7.5)
)

df |>
  gt()
Tabela 1.1: Notas dos alunos
id nome nota
1 Ana 8.5
2 Beto 9.0
3 Carla 7.5
  • head(df), tail(df): Mostra as primeiras/últimas linhas ( Tabela 1.2 ).
Código
# Tabela 1 (Esquerda)
head(df) |> 
  gt() 
# Tabela 2 (Direita)
tail(df) |> 
  gt()
Tabela 1.2: Inspeção dos Dados: Primeiras e Últimas linhas
(a) Visualização do Topo (Head)
id nome nota
1 Ana 8.5
2 Beto 9.0
3 Carla 7.5
(b) Visualização do Final (Tail)
id nome nota
1 Ana 8.5
2 Beto 9.0
3 Carla 7.5
  • nrow(df), ncol(df): Número de linhas e colunas.
Código
nrow(df) #número de linhas
[1] 3
Código
ncol(df) #número de colunas
[1] 3
  • dim(df): Retorna dimensões (linhas, colunas).
Código
dim(df) #dimensão
[1] 3 3
  • str(df), glimpse(df): Mostra a estrutura interna (tipos de dados de cada coluna).
Código
str(df)
'data.frame':   3 obs. of  3 variables:
 $ id  : int  1 2 3
 $ nome: chr  "Ana" "Beto" "Carla"
 $ nota: num  8.5 9 7.5

Essencial para depuração.

  • names(df): Retorna ou define os nomes das colunas.
Código
names(df)
[1] "id"   "nome" "nota"
  • rbind(df1, df2): É usada quando você tem dados novos com a mesma estrutura (mesmas colunas) e quer adicioná-los aos antigos ( Tabela 1.3).
Código
pacman::p_load(gt,dplyr)

grupo_jan <- data.frame(
  id = 1:2,
  vendas = c(100, 150)
)

grupo_jan %>%
  gt()
grupo_fev <- data.frame(
  id = 3:4,
  vendas = c(200, 120)
) 

grupo_fev %>%
  gt()
# Juntando (Bind de Linhas - Rows)
todos_dados <- rbind(grupo_jan, grupo_fev)
todos_dados %>%
  gt()
Tabela 1.3: Demonstração da função rbind
(a) Grupo Janeiro
id vendas
1 100
2 150
(b) Grupo Fevereiro
id vendas
3 200
4 120
(c) Resultado da União
id vendas
1 100
2 150
3 200
4 120
Importante

Os nomes das colunas devem ser exatamente iguais e estar na mesma ordem (embora data frames modernos tentem alinhar por nome, é boa prática garantir a ordem).

  • cbind(df1, df2): Esta função cola/junta dois data frames lado a lado. É uma colagem cega baseada na posição. Ela cola a linha 1 do df1 com a linha 1 do df2 ( Tabela 1.4).
Código
library(gt)
library(dplyr) # Necessário se usar o pipe %>%

df_nomes <- data.frame(nome = c("Ana", "Beto", "Carla"))
df_nomes %>%
  gt()
df_idades <- data.frame(idade = c(25, 30, 22))
df_idades %>%
  gt()
# Colando lado a lado e exibindo
df_completo <- cbind(df_nomes, df_idades)
df_completo %>%
  gt()
Tabela 1.4: Demonstração da função cbind
(a) Tabela de nomes
nome
Ana
Beto
Carla
(b) Tabela de idades
idade
25
30
22
(c) Tabela final
nome idade
Ana 25
Beto 30
Carla 22
Importante

Se a ordem das linhas estiver diferente (ex: o usuário 1 está na primeira linha da tabela A, mas o usuário 5 está na primeira linha da tabela B), seus dados ficarão corrompidos. Use apenas quando tiver certeza absoluta que a ordem das linhas é idêntica.

  • merge(x, y): Diferente do cbind, o merge ( Tabela 1.5) não depende da ordem das linhas. Ele procura uma coluna chave (ID, CPF, Código) comum entre as duas tabelas e alinha as informações corretamente. Os parâmetros importantes são, by = coluna_chave, a coluna usada para fazer o cruzamento; all = TRUE, que mantém todas as linhas (Full Outer Join) e all.x = TRUE que mantém todas as linhas da tabela da esquerda (Left Join).
Código
funcionarios <- data.frame(
  id = c(3, 1, 2),
  nome = c("Carlos", "Ana", "Bia")
)

funcionarios %>%
  gt()
salarios <- data.frame(
  id = c(1, 2, 3),
  salario = c(5000, 6000, 5500)
)
salarios %>%
  gt()
# O merge procura o 'id' igual e alinha as linhas corretamente
fusao <- merge(x = funcionarios, y = salarios, by = "id")

fusao %>%
  gt()
Tabela 1.5: Demonstração da função merge
(a) Tabela Funcionários
id nome
3 Carlos
1 Ana
2 Bia
(b) Tabela Salários
id salario
1 5000
2 6000
3 5500
(c) Resultado do Merge
id nome salario
1 Ana 5000
2 Bia 6000
3 Carlos 5500
  • summary(df): Resumo estatístico básico.
Código
summary(fusao)
       id          nome              salario    
 Min.   :1.0   Length:3           Min.   :5000  
 1st Qu.:1.5   Class :character   1st Qu.:5250  
 Median :2.0   Mode  :character   Median :5500  
 Mean   :2.0                      Mean   :5500  
 3rd Qu.:2.5                      3rd Qu.:5750  
 Max.   :3.0                      Max.   :6000  

Fatores

Fatores são usados para variáveis categóricas (qualitativas). O R armazena internamente como números inteiros (1,2,3…), mas exibe rótulos (labels). A ordem dos níveis (levels) é crucial para a ordem em gráficos.

  • factor(x, levels, ordered): Cria um fator. Definir levels é crucial para fixar a ordem das categorias (ex: em gráficos ou modelos).
Código
sexo <- c("M", "F", "F", "M") # Cria um vetor de texto

fator_sexo <- factor(sexo, levels = c("F", "M")) # Converte para fator

1.8 Entrada e Manipulação de Dados

Importação e Exportação

Para analisar os dados primeiro deve ler (importar) eles para o R/Rstudio. O pacote readr (do Tidyverse) é preferível ao R base por ser mais rápido e não converter texto em fator automaticamente.

Pacote readr (Tidyverse - Moderno e Rápido):

  • read_csv("arquivo.csv"): Lê arquivos separados por vírgula.
  • read_csv2("arquivo.csv"): Lê arquivos separados por ponto e vírgula (comum no Brasil/Europa onde a vírgula é decimal).
  • read_delim("arquivo.txt", delim = "|"): Lê arquivos com delimitadores personalizados.
  • write_csv(x, "arquivo.csv"): Salva um data frame em disco.
Código
pacman::p_load(readxl)
dados <- read_csv2("dados_brasil.csv")

write_csv(dados, "dados_limpos.csv")

# Para Excel (requer pacote extra)
dados_excel <- read_excel("planilha.xlsx", sheet = "Aba1")

Base R (Clássico):

  • read.table("arquivo.txt"): A função base mais flexível e genérica para importar dados tabulares de arquivos de texto, permitindo controle total sobre todos os parâmetros (separadores, decimais, cabeçalhos). Utilize quando o arquivo de dados não segue padrões comuns (como CSV padrão) ou quando você precisa especificar manualmente como o R deve interpretar o arquivo.
Código
# Lê arquivo separado por tabulação ('\t') com cabeçalho
dados <- read.table("dados.txt", header = TRUE, sep = "\t")
  • read.csv(): Um “wrapper” (atalho) do read.table pré-configurado especificamente para arquivos separados por vírgula (padrão internacional). Utilize para a leitura rápida de arquivos .csv padrão sem precisar configurar parâmetros extras.
Código
vendas <- read.csv("vendas_2024.csv")
dados <- readr::read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv") #usando link
ImportanteProblemas no encoding

No Português se usa vírgula (,) para decimal e acentos (Latin1/ISO-8859-1). O padrão mundial é ponto (.) para decimal e UTF-8.

  • use read_csv(): Espera separador vírgula (padrão US).

  • Use read_csv2(): Espera separador ponto-e-vírgula (padrão BR).

Se seus textos (nomes de cidades) aparecerem com símbolos estranhos (São Paulo), force o encoding

Código
pacman::p_load(readr)
dados <- read_csv2("dados_br.csv", locale = locale(encoding = "Latin1"))
  • write_csv(): Salva data frames em arquivo CSV de forma mais rápida e moderna que o write.csv base. Utilize sempre que precisar exportar dados processados para CSV, pois ele não escreve nomes de linhas (row names) por padrão e lida melhor com caracteres especiais.
Código
# Salva o arquivo sem criar aquela coluna de índice numérico (1, 2, 3...)
readr::write_csv(iris, "iris_limpo.csv")
  • scan(): Leitura primitiva e/ou função de baixo nível que lê dados sequencialmente e os converte em vetores ou listas, em vez de data frames. Utilize para ler arquivos com estrutura irregular, para colar dados copiados diretamente no console ou quando read.table falha devido a inconsistências no arquivo.
Código
# Lê números de um arquivo diretamente para um vetor numérico
vetor_números <- scan("números.txt", what = numeric())
  • save(obj, file="dados.RData"): Salva um ou mais objetos R específicos (variáveis, modelos, data frames) que estão no Environment em um arquivo binário compactado (.RData), preservando tipos e classes. Utilize para salvar resultados intermediários importantes (ex: ajustou um modelo que levou muito tempo e não quer voltar ajustar novamente) para uso futuro, sem salvar o “lixo” do ambiente de trabalho inteiro.
Código
# Você ajustou um modelo e chamou-o de fit
# O codigo abaixo salva apenas o dataframe 'dados' e o modelo 'fit' que estão no Environment
save(dados, fit, file = "resultados_parciais.RData")
  • load("dados.RData"): Carrega objetos salvos em arquivos .RData diretamente para a memória do R, mantendo os nomes originais dos objetos. Utilize para retomar análises carregando dados pré-processados ou modelos salvos, economizando o tempo de rodar scripts novamente.
Código
load("resultados_parciais.RData")
  • save.image(): Um atalho que salva todos os objetos presentes no seu ambiente de trabalho (Workspace) atual em um único arquivo. Utilize ao encerrar uma sessão de trabalho complexa para garantir que você possa continuar exatamente de onde parou (geralmente salva como .RData).
Código
save.image(file = "backup_projeto_tarde.RData")

Excel e Google Sheets:

  • readxl::read_excel("arq.xlsx", sheet = 1): A função mais robusta e eficiente para importar dados de arquivos Microsoft Excel (.xls e .xlsx) sem depender de instalações externas complexas (como Java). Utilize para carregar dados armazenados localmente em arquivos Excel, permitindo especificar qual aba (sheet) deve ser lida pelo nome ou índice.
Código
tabela <- readxl::read_excel("relatorio_anual.xlsx", sheet = "Dados_Brutos")
  • googlesheets4::read_sheet("URL"): Função que conecta diretamente à API do Google para baixar e importar dados de planilhas hospedadas na nuvem (Google Drive), gerenciando a autenticação do usuário. Utilize para acessar dados diretamente pela URL ou ID da planilha, eliminando a necessidade de baixar o arquivo manualmente antes de ler.
Código
dados_online <- googlesheets4::read_sheet("https://docs.google.com/spreadsheets/d/...")

Ler dados de alta dimensão (Big Data)

  • read_parquet(): Lê arquivos no formato Parquet do pacote arrow, um formato de armazenamento colunar altamente comprimido e eficiente, amplamente usado em Big Data. Utilize para importar grandes volumes de dados (milhões de linhas) com extrema rapidez e baixo uso de memória.
Código
dados_gigantes <- read_parquet("dados_grandes.parquet")
  • write_parquet(): Salva um data frame ou tibble no formato Parquet. Utilize para armazenar dados processados ocupando muito menos espaço em disco que um CSV e permitindo leituras futuras muito mais rápidas.
Código
write_parquet(iris, "iris_otimizado.parquet")
  • saveRDS() salva um único objeto do R em um arquivo binário, sem salvar o nome original da variável. A melhor opção para salvar objetos individuais para ser carregado posteriormente com qualquer nome.
Código
# Vc ajustou modelo e pode salvar apenas o resultado final em um arquivo .rds
saveRDS(modelo_final, "meu_modelo.rds")
  • readRDS(): Lê um arquivo .rds e retorna o objeto salvo, exigindo que você o atribua a uma nova variável. Utilize para carregar objetos salvos com saveRDS. Diferente de load(), ele não suja seu ambiente com nomes variáveis desconhecidos; você escolhe o nome.
Código
# Carrega o modelo salvo atribuindo a uma nova variável
modelo_carregado <- readRDS("meu_modelo.rds")

1.9 Manipulação com dplyr (Tidyverse)

O padrão ouro atual para manipulação de dados. Utiliza o operador pipe %>% para encadear ações de forma legível.

Algumas funções:

  • select(df, col1, col2): Seleciona colunas e mantém apenas as colunas selecionadas em um data frame. Utilize para reduzir o conjunto de dados, descartando variáveis irrelevantes para a análise atual ou para reordenar colunas.
Código
# Seleciona apenas as colunas Sepal.Length e Species
iris %>% select(Sepal.Length, Species)%>%
  reactable(  searchable = TRUE,
)
  • filter(df, condicao): Filtra linhas baseado em condições lógicas. Utilize para extrair observações específicas, como “apenas vendas acima de 100” ou “apenas dados de 2024”.
Código
# Filtra apenas linhas da espécie setosa
iris %>% filter(Species == "setosa")%>%
  reactable(  sortable = TRUE,
  resizable = TRUE,
  filterable = TRUE,
  searchable = TRUE)
  • mutate(df, nova_col = x + y): Cria ou modifica colunas existentes preservando as demais. Utilize para criar cálculos (ex: conversão de unidades), transformar dados ou criar variáveis derivadas.
Código
# Cria uma nova coluna com a razão (divisão) entre sépala e pétala
iris %>% mutate(razao = Sepal.Length / Petal.Length)%>%
  reactable(  sortable = TRUE,
  resizable = TRUE,
  filterable = TRUE,
  searchable = TRUE)
  • arrange(df, col): Ordena as linhas. Use desc(col) para ordem decrescente. Utilize para classificar dados, como colocar os maiores valores no topo (desc()) ou ordenar alfabeticamente.
Código
# Ordena por Sepal.Length de forma decrescente
iris %>% arrange(desc(Sepal.Length))%>%
  reactable()
  • summarise(df, media = mean(x)): Reduz múltiplos valores a um único resumo estatístico (soma, média, contagem). Utilize, geralmente após um group_by, para obter métricas agregadas dos seus dados.
Código
# Calcula a média do comprimento das sépalas
iris %>% summarise(media_sepala = mean(Sepal.Length))%>%
  gt()
media_sepala
5.843333
  • group_by(df, categoria): Agrupa os dados. Utilize imediatamente antes de summarise ou mutate para aplicar a cada grupo separadamente.
Código
# Agrupa por espécie (preparação para cálculo subsequente)
iris %>% group_by(Species)%>%
  reactable(filterable = TRUE,
  searchable = TRUE,)
  • rename(df, novo = velho): Renomeia colunas. Utilize para tornar nomes de variáveis mais legíveis ou compatíveis com padrões de código (novo_nome = velho_nome).
Código
# Renomeia Sepal.Length para comprimento_sepala
iris %>% rename(comprimento_sepala = Sepal.Length)%>%
  reactable(filterable = TRUE,
  searchable = TRUE,)
  • relocate(df, col, .before = col2): Reordena a posição das colunas. Isto é, move colunas para novas posições dentro do data frame. Utilize para organizar a visualização, trazendo colunas importantes para o início (.before ou .after).
Código
# Move a coluna Species para antes de todas as outras

iris %>% relocate(Species, .before = everything())%>%
  reactable()
  • slice(df, n:m): Seleciona linhas baseando-se em suas posições (índices) inteiras. Utilize quando precisar de linhas específicas pela posição, como as 5 primeiras ou a última linha, independente dos valores ( Tabela 1.6).
Código
# Seleciona da linha 10 até a linha 15
iris %>% slice(10:15)%>%
  gt()
Tabela 1.6: Linhas 10 a 15 do conjunto de dados flor Iris
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
4.9 3.1 1.5 0.1 setosa
5.4 3.7 1.5 0.2 setosa
4.8 3.4 1.6 0.2 setosa
4.8 3.0 1.4 0.1 setosa
4.3 3.0 1.1 0.1 setosa
5.8 4.0 1.2 0.2 setosa
  • recode(): Substitui valores específicos num vetor numérico ou de caracteres ( Tabela 1.7). Utilize dentro de um mutate para corrigir erros de digitação ou traduzir categorias específicas rapidamente (Substituído modernamente por case_match).
Código
# Renomeia "setosa" para "Setosa_Pura" na coluna Species
iris %>% mutate(Species = recode(Species, "setosa" = "Setosa_Pura"))%>%
  reactable()
Tabela 1.7: Coluna Species renomeada de Setosa para Setosa_Pura
  • across(): Função auxiliar que permite aplicar uma mesma transformação ou função de resumo a múltiplas colunas selecionadas simultaneamente. Utilize dentro de mutate() ou summarise() quando precisar repetir a mesma operação (ex: calcular média, converter tipo) em várias variáveis sem duplicar código ( Tabela 1.8).
Código
# Exemplo: Calcular a média apenas das colunas que começam com "Sepal"
iris %>%
  summarise(across(starts_with("Sepal"), mean))%>%
  gt()
Tabela 1.8: Média das Sepalas
Sepal.Length Sepal.Width
5.843333 3.057333
  • case_when(): Uma estrutura condicional vetorizada que permite criar ou modificar valores baseando-se em uma sequência de múltiplas condições lógicas (como vários if-else encadeados). Utilize para categorizar variáveis ou criar novas colunas baseadas em regras complexas, evitando o uso confuso de múltiplos ifelse() aninhados (Table Tabela 1.9).
Código
# Exemplo: Categorizar o tamanho da pétala em Pequena, Média, Grande
iris %>%
  mutate(Categoria = case_when(
    Petal.Length < 2 ~ "Pequena",
    Petal.Length < 5 ~ "Média",
    TRUE ~ "Grande" # 'TRUE' age como o 'else' (caso contrário) final
  )) %>%
  head()%>%
  gt()
Tabela 1.9: Pétala categorizadas em pequena, média, grande
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Categoria
5.1 3.5 1.4 0.2 setosa Pequena
4.9 3.0 1.4 0.2 setosa Pequena
4.7 3.2 1.3 0.2 setosa Pequena
4.6 3.1 1.5 0.2 setosa Pequena
5.0 3.6 1.4 0.2 setosa Pequena
5.4 3.9 1.7 0.4 setosa Pequena
Código
# "Pegue o df, ENTÃO filtre notas altas, ENTÃO crie uma coluna de status"
df_novo <- df %>%
  filter(nota > 8) %>%
  mutate(status = "Aprovado com Louvor") %>%
  select(nome, status)

# Agrupamento
resumo <- df %>%
  group_by(nome) %>%   # Supondo que 'nome' seja uma categoria
  summarise(
    media_nota = mean(nota, na.rm = TRUE),
    total = n() 
  )

Joins (Combinação de Tabelas):

  • left_join(x, y, by = "key"): Mantém todas as linhas de x, traz correspondências de y, baseando-se na coluna key em comum entre x e y. Isto é, combina duas tabelas mantendo todas as linhas da tabela da esquerda (x) e adicionando as colunas da direita (y) onde houver correspondência na chave (key). Utilize para enriquecer uma tabela principal com dados auxiliares sem perder observações originais.
Código
# Adiciona dados dos produtos à tabela de vendas
vendas_detalhadas <- left_join(vendas, produtos, by = "id_produto")
  • inner_join(x, y): Mantém apenas linhas que existem em ambas as tabelas. Isto é, retorna apenas as linhas onde a chave de ligação existe simultaneamente em ambas as tabelas (interseção), descartando o resto. Utilize quando você precisa analisar apenas casos completos que tenham dados em ambas as fontes.
Código
# Mantém apenas alunos que têm notas registradas
alunos_com_notas <- inner_join(alunos, notas, by = "matricula")
  • full_join(x, y): Mantém todas as linhas de ambas as tabelas. Onde não houver correspondência, o R preenche os valores faltantes com NA. Utilize para garantir que nenhum dado seja perdido de nenhum dos lados, ideal para comparar cadastros discrepantes.
Código
presenca_total <- full_join(dia_1, dia_2, by = "nome_aluno")
  • anti_join(x, y): Retorna linhas de x que NÃO têm correspondência em y. Essencial para identificar inconsistências entre duas bases de dados.
Código
# Encontra produtos cadastrados que nunca foram vendidos
produtos_encalhados <- anti_join(produtos, vendas, by = "id_produto")
  • pivot_longer(df, cols, ...): Transforma colunas em linhas (formato longo). Útil quando variáveis estão espalhadas no cabeçalho (ex: anos 2000, 2001, 2002). Ist é, converte tabela “larga” para “longa”, empilhando cabeçalhos de colunas em uma única variável categórica e seus valores em outra ( Tabela 1.10) .
Código
# Transforma colunas de anos (2000 a 2010) em: coluna 'ano' e coluna 'pib'
df_longo <- pivot_longer(pib_paises, cols = `2000`:`2010`, names_to = "ano", values_to = "pib")
  • pivot_wider(df, names_from, values_from): Transforma linhas em colunas (formato largo). Isso é, é o inverso do anterior (pivot_longer(df, cols, ...)); expande categorias de uma coluna em múltiplas colunas novas, preenchendo com valores associados. Utilize para criar tabelas de resumo final (pivot tables) legíveis para humanos ou relatórios em Excel ( Tabela 1.10) .
Código
# Transforma a coluna 'tipo_despesa' em várias colunas (Aluguel, Comida, etc)
df_largo <- pivot_wider(financas, names_from = tipo_despesa, values_from = valor)
Código
pacman::p_load(gt,dplyr,tidyr)

dados_largo <- data.frame(pais = "Brasil", ano2020 = 10, ano2021 = 12)

# Tabela 1 (Esquerda)
dados_largo %>%
  gt()
# Transformação
dados_longo <- dados_largo %>%
  pivot_longer(
    cols = c(ano2020, ano2021),
    names_to = "ano",
    values_to = "pib"
  )

# Tabela 2 (Direita)
dados_longo %>%
  gt()
Tabela 1.10: Transformação de dados com pivot_longer
(a) Dados Largos (Original)
pais ano2020 ano2021
Brasil 10 12
(b) Dados Longos (Resultado)
pais ano pib
Brasil ano2020 10
Brasil ano2021 12
  • separate(df, col, ...): Divide uma coluna de texto em múltiplas novas colunas usando um caractere separador (ponto, traço, barra). Útil para quebrar datas (2024-12-01), nomes completos ou códigos compostos (BR-SP-01) em componentes individuais.
Código
# Divide "2024-12-01" em três colunas: ano, mes, dia
df_limpo <- separate(df, data_string, into = c("ano", "mes", "dia"), sep = "-")
  • unite(df, ...): Junta várias colunas em uma string única. É operação inversa ao separate; concatena valores de múltiplas colunas em uma única string, inserindo um separador. Utilize para criar chaves únicas combinando ID e Data, ou juntar Nome e Sobrenome.
Código
# Junta 'ddd' e 'número' para formar 'telefone_completo'
df_contato <- unite(df, "telefone_completo", ddd, número, sep = " ")
  • any(is.na(.)) e sum(is.na(.)): Funções lógicas que varrem os dados para detectar a existência de algum (any) ou quantificar/somar (sum) valores ausentes. Obrigatório na Análise Exploratória (EDA) para decidir se você deve remover as linhas (drop_na) ou realizar imputação.
Código
# Verifica se existe algum NA em cada coluna do dataframe
iris %>% summarise(across(everything(), ~any(is.na(.))))
Código
# Conta quantos NAs existem em cada coluna
iris %>% summarise(across(everything(), ~sum(is.na(.))))
  • drop_na(df): Remove linhas inteiras se houver qualquer valor ausente (NA) nas colunas especificadas (ou em todas, se nenhuma for citada). Para limpeza rápida de dados onde observações incompletas não são úteis para a modelagem estatística.
Código
df_limpo <- drop_na(cliente_df, idade, renda)
  • fill(df): Substitui valores NA propagando o último valor válido observado anterior/posterior.
Código
# Preenche os NAs da cotação com o valor do dia anterior (down)
df_preenchido <- fill(acoes, cotacao, .direction = "down")
  • tidyr::replace_na(): Substitui valores ausentes por um valor fixo específico (como zero ou “Desconhecido”). Utilize quando o valor ausente tem um significado real (ex: falta de registro de dívida significa dívida zero) ou para variáveis categóricas.
Código
# Substitui NA na coluna 'Species' por "Não Identificada"
df_limpo <- df %>% 
  mutate(Species = replace_na(Species, "Não Identificada"))
Código
# Substitui NAs da coluna 'Sepal.Length' pela sua média
df_imputado <- iris %>% 
  mutate(Sepal.Length = if_else(is.na(Sepal.Length), 
                                mean(Sepal.Length, na.rm = TRUE), 
                                Sepal.Length))
  • mice::mice(): Multivariate Imputation by Chained Equations. Cria múltiplos datasets completos estimando os valores faltantes com base nas correlações com outras variáveis (regressão, florestas aleatórias, etc.). Utilize quando a imputação pela média introduziria viés nos seus modelos e a eliminação dos valores ausentes faria-lhe perder muita informação.
Código
# Cria 5 datasets com dados imputados usando método padrão (pmm)
dados_imputados <- mice(iris, m = 5, method = 'pmm', printFlag = FALSE)

# Completa o dataset final (pega o primeiro dos 5 gerados)
df_final <- complete(dados_imputados, 1)

1.10 Manipulação de Strings (stringr)

  • paste(..., sep), paste0(): paste concatena/junta vetores de strings usando um separador especificado; paste0 é um atalho que concatena sem separador. Utilize para criar chaves compostas, frases dinâmicas ou combinar colunas (ex: Nome + Sobrenome).
Código
# paste junta com espaço padrão; paste0 cola tudo junto
nome_comp <- paste("João", "Silva", sep = "_") # resultado "João_Silva"
cod_id <- paste0("ID", 123)                    # # resultado "ID123"
  • str_detect(string, pattern): Retorna um vetor lógico (TRUE/FALSE) indicando se um padrão (texto fixo ou Regex) existe na string. Essencial dentro de um filter() para selecionar linhas que contenham termos específicos (ex: emails que contêm @gmail).
Código
# Filtra apenas frutas que terminam com "a" (regex $)
frutas_a <- frutas %>% filter(str_detect(nome, "a$"))
  • str_replace(string, pattern, replacement), str_replace_all(): Substitui ocorrências de um padrão (pattern) por um novo texto. str_replace altera apenas a primeira ocorrência encontrada; str_replace_all altera todas. Utilize para limpeza de dados, como remover símbolos de moeda, corrigir erros de digitação recorrentes ou padronizar nomes.
Código
# Remove o cifrão e vírgulas para converter em número depois
valor_limpo <- str_replace_all("R$ 1.200,00", "[R$.]", "")
  • str_sub(string, start, end): Extrai ou substitui partes de uma string baseando-se em posições de índices (início e fim). Utilize quando os dados têm posição fixa, como extrair o DDD de um telefone (caracteres 1 e 2) ou o ano de uma data sem separadores.
Código
# Pega os 3 primeiros caracteres da string
prefixo <- str_sub("São Paulo", start = 1, end = 3) # resultado"São"
  • str_extract() / str_extract_all(): Extrai o texto real que corresponde a um padrão (Regex), ignorando o resto da string. Utilize para “pescar” informações específicas dentro de um texto sujo, como extrair apenas números de um endereço ou apenas o domínio de um email.
Código
# Extrai apenas a sequência de dígitos da string
número <- str_extract("Pedido número 4502 enviado", "\\d+") #resultado "4502"
  • str_to_lower() / str_to_upper(): Converte todo o texto para minúsculas (lower) ou maiúsculas (upper). Passo obrigatório antes de fazer junção ou comparações de texto para evitar que “Brasil” seja diferente de “brasil”.
Código
# Normaliza os nomes para evitar duplicidade de caixa
nomes_norm <- str_to_lower(c("Ana", "ANA", "ana"))
  • str_squish(): Remove espaços em branco no início e no fim da string, e também reduz múltiplos espaços internos consecutivos a um único espaço. Muito superior ao str_trim para limpar dados digitados por humanos, removendo acidentes como “Nome Sobrenome”.
Código
# Transforma "  Data   Science  " em "Data Science"
texto_limpo <- str_squish("  Data   Science  ")
  • str_glue(): Uma evolução moderna do paste, permite inserir variáveis diretamente dentro da string usando chaves {}. Utilize para tornar o código mais legível ao criar mensagens de log, títulos de gráficos ou URLs dinâmicas.
Código
nome <- "Maria"; idade <- 30
msg <- str_glue("A aluna {nome} tem {idade} anos.") # Retorna "A aluna Maria tem 30 anos

1.11 Datas (lubridate)

  • ymd(), dmy(), mdy(): Funções que convertem texto em objetos Date. O nome da função dita a ordem esperada dos componentes (y=ano, m=mês, d=dia). Utilize para transformar colunas de texto (importadas de CSVs/Excel) em datas reais, independentemente do separador (barra, traço, ponto) usado no texto original.
Código
pacman::p_load(lubridate)
# Converte texto "2023/12/25" ou "2023-12-25" para data
natal <- ymd("20231225") 
data_br <- dmy("31/01/2024") # Dia, Mês, Ano
  • years(), months(), days(): Criam objetos de “Período” que permitem aritmética intuitiva com datas, lidando automaticamente com nuances como anos bissextos ou meses com 30/31 dias. Utilize para calcular datas de vencimento, projetar cenários futuros ou filtrar dados de um período específico (“últimos 3 meses”).
Código
# Adiciona 1 ano e 6 meses a uma data
vencimento <- ymd("2024-01-01") + years(1) + months(6)
  • ymd_hms() (e suas variantes): Similar ao ymd(), mas para dados que incluem horário (timestamp: Hora, Minuto, Segundo). Cria objetos POSIXct. Essencial para analisar logs de servidor, transações financeiras intraday ou qualquer dado onde a hora exata importa.
Código
# Lê data e hora com fuso horário UTC
momento_exato <- ymd_hms("2024-05-10 14:30:59", tz = "UTC")
  • year(), month(), wday(): Funções que retornam apenas uma parte específica da data (o ano, o mês ou o dia da semana). Fundamental para análise de sazonalidade (ex: “vendas por dia da semana” ou “evolução anual”). O argumento label = TRUE em wday retorna o nome (Dom, Seg…) em vez do número.
Código
data <- ymd("2024-12-25")
mes <- month(data)         # Retorna 12
dia_sem <- wday(data, label = TRUE) # Retorna "Wed" (ou "qua" dependendo do locale)
  • floor_date(): Arredonda uma data para baixo até a unidade de tempo especificada (semana, mês, hora). A função mais importante para agrupar séries temporais. Use para transformar dados diários em mensais/semanais antes de um group_by.
Código
# Agrupa todas as datas para o primeiro dia do respectivo mês
vendas %>% 
  mutate(mes_referencia = floor_date(data_venda, unit = "month"))
  • today() / now(): Retornam, respectivamente, a data atual (Date) e o instante atual exato (POSIXct) do sistema. Utilize para calcular a idade de registros (“dias desde o cadastro até hoje”) ou para carimbar data de execução em relatórios.
Código
# Calcula a diferença em dias entre hoje e uma data passada
dias_passados <- today() - ymd("2000-01-01")
  • interval() e %--%: Cria um objeto de intervalo entre duas datas, permitindo cálculos precisos de duração. Use para verificar se uma data cai dentro de um período específico ou para calcular a duração exata em segundos/anos entre dois pontos.
Código
inicio <- ymd("2023-01-01")
fim <- today()
meu_intervalo <- interval(inicio, fim) # ou inicio %--% fim

# Verifica se a data X está dentro do intervalo
ymd("2023-06-01") %within% meu_intervalo

1.12 Funções Matemáticas Básicas

  • sum() / prod(): Calculam, respectivamente, o somatório \((\sum)\) e o produtório \((\prod)\) de todos os valores de um vetor numérico. Utilize para agregações básicas, verificações de totais (ex: receita total) ou cálculos de probabilidade conjunta (produtório).
Código
total <- sum(c(10, 20, 30))  # 60
fatorial_simples <- prod(1:5) # 1 * 2 * 3 * 4 * 5 = 120
  • min() / max(): Retornam o valor mais baixo e o mais alto de um conjunto de dados. Utilize para identificar limites (inferiores e superiores), detectar outliers óbvios ou definir escalas de gráficos.
Código
# Encontra o valor máximo ignorando NAs
maior_nota <- max(c(5, 8, 9, NA), na.rm = TRUE)
  • range(): Retorna um vetor de dois elementos contendo o mínimo e o máximo: c(min, max). Não retorna a amplitude (diferença) diretamente. Utilize para verificar rapidamente a extensão dos dados ou definir os limites (limits) de eixos em gráficos.
Código
limites <- range(iris$Sepal.Length) # Retorna c(4.3, 7.9)
amplitude <- diff(limites)          # Calcula a diferença (3.6)
  • round(): Arredonda números para um número especificado de casas decimais seguindo o padrão internacional (arredonda para o par mais próximo). Utilize para formatar saídas para relatórios ou simplificar a visualização de números com muitas casas decimais.
Código
# Arredonda para 2 casas
pi_curto <- round(3.14159, digits = 2) # 3.14
  • abs(): Retorna o valor absoluto (módulo) de um número, ignorando o sinal negativo (\(|x|\)). Utilize para calcular distâncias, erros absolutos (diferença entre previsto e real) ou magnitudes.
Código
# Transforma diferenças negativas em positivas
erro_absoluto <- abs(-50) # 50
  • log() / exp(): log calcula o logaritmo natural (\(\ln\), base \(e\)) e exp calcula a exponencial (\(e^x\)). Para base 10, use log10(). Utilize para transformar dados assimétricos (normalizar distribuição), calcular retornos financeiros ou reverter transformações logarítmicas.
Código
# Transformação Log para reduzir assimetria de salários
log_salario <- log(c(1000, 10000, 100000)) 
  • cumsum(): Retorna a soma acumulada dos elementos. O resultado tem o mesmo tamanho do vetor original. Essencial para criar Gráficos de Pareto, calcular saldos bancários dia a dia ou frequências acumuladas.
Código
vendas_diarias <- c(10, 20, 5)
acumulado <- cumsum(vendas_diarias) # Retorna 10, 30, 35

1.13 Estatística Descritiva

  • mean() / median(): Calculam a média aritmética (centro de gravidade) e a mediana (valor central que divide a amostra em 50/50). Use a média para distribuições normais e a mediana quando houver outliers (valores extremos) que distorcem a média.
Código
salarios <- c(1000, 1200, 50000) # O 50000 distorce a média
media <- mean(salarios)   # 17400 (Distorcida)
mediana <- median(salarios) # 1200 (Representativa)
  • sd() / var(): Calculam o desvio padrão e a variância amostral (\(n-1\)), medidas de dispersão que indicam o quanto os dados variam em torno da média. Utilize para quantificar o risco, volatilidade ou a consistência de um processo.
Código
# Calcula o desvio padrão ignorando falhas
volatilidade <- sd(c(10, 12, 9, NA), na.rm = TRUE)
  • quantile(): Divide os dados ordenados em probabilidades específicas. Por padrão retorna mín, 25%, 50%, 75%, máx. Utilize para entender a distribuição detalhada, criar Boxplots manuais ou identificar faixas de valores (ex: “os 10% mais ricos”).
Código
# Calcula os decis (10%, 20%... 90%)
decis <- quantile(iris$Sepal.Length, probs = seq(0, 1, 0.1))
  • cor(): Calcula a força e direção da relação linear entre duas variáveis (vai de -1 a 1). Utilize na análise exploratória para checar multicolinearidade ou se uma variável influencia a outra.
Código
correlacao <- cor(iris$Sepal.Length, iris$Petal.Length, use = "complete.obs")
  • summary(): Uma função polimórfica que retorna um “raio-x” do objeto. Para vetores numéricos, dá as medidas descritivas; para fatores, a contagem. O primeiro comando a rodar ao receber dados novos para ter uma visão geral rápida da distribuição e identificar NAs.
Código
summary(iris) # Resumo de todas as colunas do dataset
  • table() / prop.table(): table cria tabelas de frequência (contagem) para dados categóricos; prop.table converte essas contagens em porcentagens/proporções. Fundamental para analisar variáveis qualitativas (ex: “Quantos clientes são de SP vs RJ?”).
Código
contagem <- table(iris$Species)
porcentagem <- prop.table(contagem) * 100 # Em %
  • scale(): Padroniza (normaliza) os dados subtraindo a média e dividindo pelo desvio padrão (Z-score), \(z=\frac{x-\bar{x}}{\sigma}\). Obrigatório antes de algoritmos de Machine Learning baseados em distância (como K-means ou KNN) para que variáveis grandes não dominem as pequenas.
Código
# Coloca os dados na mesma escala (Média 0, SD 1)
dados_normalizados <- scale(iris[, 1:4])
  • unique() / length(): unique retorna os valores únicos (sem repetição); length conta o tamanho total do vetor. Use a combinação length(unique(x)) para saber a cardinalidade (quantos itens distintos existem).
Código
qtd_especies <- length(unique(iris$Species)) # 3

Aqui estão as definições aprimoradas para distribuições e modelagem estatística, organizadas para clareza e aplicação prática.

1.14 Distribuições de Probabilidade (Prefixos d, p, q, r)

O R utiliza um sistema consistente: [prefixo][distribuição]. Ex: norm, binom, pois, exp, unif, t, chisq, f.

d… (Densidade/Probabilidade Pontual): Calcula a altura da curva da densidade (PDF) para variáveis contínuas, ou a probabilidade exata \(P(X=x)\) para variáveis discretas. Utilize para desenhar o gráfico da distribuição ou calcular verossimilhança (Likelihood).

Código
# Qual a probabilidade exata de obter 2 caras em 3 lançamentos (Binomial)?
prob_exata <- dbinom(x = 2, size = 3, prob = 0.5) 
  • p... (Probabilidade Acumulada - CDF): Calcula a área sob a curva à esquerda de um ponto \(P(X \le x)\). Utilize para calcular valores-p ou a probabilidade de uma variável ser menor que um certo valor.
Código
# Qual a probabilidade de um valor numa Normal(0,1) ser menor que -1.96?
prob_acumulada <- pnorm(-1.96) # ~0.025 (2.5%)
  • q... (Quantil - Inverso da CDF): Dado uma probabilidade (área), retorna o valor de \(x\) correspondente. Utilize para encontrar valores críticos para intervalos de confiança (ex: o Z para 95%).
Código
# Qual valor deixa 2.5% da cauda superior na distribuição T (gl=29)?
valor_critico <- qt(p = 0.975, df = 29) 
  • r... (Random - Geração de números (pseudo) Aleatória): Gera números (pseudo) aleatórios que seguem a distribuição especificada. Utilize para simulações de Monte Carlo, criar dados sintéticos ou bootstrap.
Código
# Gera 100 observações de uma Poisson com lambda = 5
amostra <- rpois(n = 100, lambda = 5)

1.15 Testes de Hipótese

  • t.test(): Realiza o teste T de Student para comparar médias de uma ou duas amostras (independentes ou pareadas). Utilize para verificar se há diferença significativa entre dois grupos numéricos (ex: tratamento vs controle).
Código
pacman::p_load(mtcars)
# Compara se há diferença significativa no consumo (mpg) entre carros automáticos e manuais (am) no dataset mtcars.
resultado <- t.test(mpg ~ am, data = mtcars)
  • cor.test(): Testa se a correlação entre duas variáveis é significativamente diferente de zero. Utilize para validar estatisticamente a associação linear observada com cor().
Código
# Testa a correlação entre o peso do carro (wt) e a eficiência (mpg). Espera-se uma correlação negativa forte.
teste_cor <- cor.test(mtcars$wt, mtcars$mp, method = "pearson")
  • chisq.test(): Teste Qui-Quadrado de independência. Utilize para verificar associação entre duas variáveis categóricas (ex: Cor dos Olhos vs Cor do Cabelo).
Importante

A entrada ideal é uma tabela de contingência (table(.)).

Código
# Verifica se existe associação entre o tipo de motor (vs: em V ou reto) e o tipo de transmissão (am: auto ou manual).
teste_qui <- chisq.test(table(mtcars$vs, mtcars$am))
  • shapiro.test(): Teste de normalidade de Shapiro-Wilk (\(H_0\): Os dados seguem uma distribuição Normal). Utilize para verificar os pressupostos de normalidade dos resíduos de um modelo ou de uma variável antes de aplicar testes paramétricos. (Melhor para \(N < 5000\)).
Código
# P-valor < 0.05 indica que os dados NÃO são normais
teste_norm <- shapiro.test(resid(modelo_linear)) 
#Verifica se a largura das sépalas (Sepal.Width) das flores iris segue uma distribuição Normal.
Shap <- shapiro.test(iris$Sepal.Width) # H0: Os dados são normais (p > 0.05 indica normalidade)
  • wilcox.test(): Versão não-paramétrica do Teste T (Teste de Mann-Whitney ou Wilcoxon). Utilize para comparar grupos quando a suposição de normalidade falha. Compara postos (ranks) e não médias.
Código
# Comparação sem assumir normalidade
teste_np <- wilcox.test(valor ~ grupo, data = dados)

1.16 Modelagem Estatística

  • lm(): Ajusta modelos de regressão linear (Mínimos Quadrados Ordinários - OLS). A base para prever uma variável numérica contínua baseada em preditores. Use summary() no objeto para ver os coeficientes e \(R^2\).
Código
# Modela o consumo de combustível (mpg) baseando-se no peso (wt) e na potência (hp) dos carros.
modelo_linear <- lm(mpg ~ wt + hp, data = mtcars)
summary(modelo_linear) #saída do modelo, embora não elegante

Call:
lm(formula = mpg ~ wt + hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-3.941 -1.600 -0.182  1.050  5.854 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 37.22727    1.59879  23.285  < 2e-16 ***
wt          -3.87783    0.63273  -6.129 1.12e-06 ***
hp          -0.03177    0.00903  -3.519  0.00145 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.593 on 29 degrees of freedom
Multiple R-squared:  0.8268,    Adjusted R-squared:  0.8148 
F-statistic: 69.21 on 2 and 29 DF,  p-value: 9.109e-12
Dica

Usar summary(modelo_ajustado) é forma mais simples mas não profissional para trabalhos acadêmicos. Existem vários pacotes que permitem uma extração mais profissional, como segue abaixo.

Código
pacman::p_load(broom, dplyr)
# Extraido os resultados do modelo ajustado acima de forma mais profissional
resultados_tidy <- tidy(modelo_linear, conf.int = TRUE)
gt(resultados_tidy)
term estimate std.error statistic p.value conf.low conf.high
(Intercept) 37.22727012 1.59878754 23.284689 2.565459e-20 33.95738245 40.49715778
wt -3.87783074 0.63273349 -6.128695 1.119647e-06 -5.17191604 -2.58374544
hp -0.03177295 0.00902971 -3.518712 1.451229e-03 -0.05024078 -0.01330512
Código
# Agora você pode acessar o p-valor assim: resultados_tidy$p.value[2]

#Resumo do modelo (R^2, AIC, etc)
qualidade_modelo <- glance(modelo_linear)
gt(qualidade_modelo)
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC deviance df.residual nobs
0.8267855 0.8148396 2.593412 69.21121 9.109054e-12 2 -74.32617 156.6523 162.5153 195.0478 29 32
Código
# Diagnóstico (Valores preditos e resíduos linha a linha)
diagnostico <- augment(modelo_linear)
reactable(diagnostico,   filterable = TRUE,
  searchable = TRUE)
  • glm(): Modelos Lineares Generalizados. Estende a regressão linear para variáveis resposta não-normais através de funções de ligação (link function). Utilize para Regressão Logística (family=binomial - resposta 0/1) ou Contagem (family=poisson), etc.
Código
pacman::p_load(report) 
# Prevê a probabilidade de um carro ser automático ou manual (am, binário 0/1) baseado no consumo (mpg).
modelo_log <- glm(am ~ mpg, family = "binomial", data = mtcars)
report(modelo_log) #Gera interpretação em inglês.
We fitted a logistic model (estimated using ML) to predict am with mpg
(formula: am ~ mpg). The model's explanatory power is substantial (Tjur's R2 =
0.37). The model's intercept, corresponding to mpg = 0, is at -6.60 (95% CI
[-12.33, -2.77], p = 0.005). Within this model:

  - The effect of mpg is statistically significant and positive (beta = 0.31, 95%
CI [0.12, 0.59], p = 0.008; Std. beta = 1.85, 95% CI [0.74, 3.54])

Standardized parameters were obtained by fitting the model on a standardized
version of the dataset. 95% Confidence Intervals (CIs) and p-values were
computed using a Wald z-distribution approximation.
Código
pacman::p_load(gtsummary) #mais técnico

modelo_linear %>%
  tbl_regression(
    intercept = TRUE,         # Mostrar o intercepto 
    estimate_fun = ~ style_number(.x, digits = 3) # Formatar casas decimais
  ) %>%
  add_global_p() %>%          # Adiciona p-valor global se tiver variáveis categóricas
  bold_p(t = 0.05) %>%        # Negrito nos valores-p significativos
  add_glance_source_note(     # Adiciona R^2 e estatísticas no rodapé
    label = list(r.squared ~ "$R^2$", AIC ~ "AIC")
  )
Characteristic Beta 95% CI p-value
(Intercept) 37.227 33.957, 40.497 <0.001
wt -3.878 -5.172, -2.584 <0.001
hp -0.032 -0.050, -0.013 0.001
Abbreviation: CI = Confidence Interval
\(R^2\) = 0.827; Adjusted R² = 0.815; Sigma = 2.59; Statistic = 69.2; p-value = <0.001; df = 2; Log-likelihood = -74.3; AIC = 157; BIC = 163; Deviance = 195; Residual df = 29; No. Obs. = 32
  • gam() (do pacote mgcv): Modelos Aditivos Generalizados. Estende os GLMs permitindo modelar relações não-lineares e formas livres (curvas) através de funções de suavização (smooth functions, denotadas por s()). Utilize quando a relação entre X e Y não for uma linha reta simples.
Código
pacman::p_load(mgcv, report,ggplot2, gtsummary) 

# Prevê o consumo (mpg) baseado na potência (hp) assumindo uma relação não-linear (curva suave)
# Note o uso de s() para indicar um termo de suavização (spline)
modelo_gam <- gam(mpg ~ s(hp), data = mtcars)

report(modelo_gam) # Gera interpretação textual descrevendo a não-linearidade.
We fitted a linear model (estimated using GCV and magic optimizer) to predict
mpg with hp (formula: mpg ~ s(hp)). The model's explanatory power is
substantial (R2 = 0.73). The model's intercept, corresponding to hp = 0, is at
20.09 (95% CI [18.97, 21.21], p < .001). Within this model:

  - The effect of Smooth term (hp) is statistically significant and NA (beta = ,
p < .001; Std. beta = , )

Standardized parameters were obtained by fitting the model on a standardized
version of the dataset.
Código
modelo_gam %>%
  tbl_regression(
    intercept = TRUE,             # Mostrar o intercepto
    estimate_fun = ~ style_number(.x, digits = 3) # Formatar casas decimais
  ) 
Characteristic Beta 95% CI p-value
(Intercept) 20.091 19.015, 21.166 <0.001
s(hp)

<0.001
Abbreviation: CI = Confidence Interval
Código
# Criando a previsão para plotar
pred_data <- data.frame(hp = seq(min(mtcars$hp), max(mtcars$hp), length = 100))
pred_data$fit <- predict(modelo_gam, newdata = pred_data)

ggplot() +
  geom_line(data = pred_data, aes(x = hp, y = fit), color = "blue", size = 1) +
  geom_rug(data = mtcars, aes(x = hp), sides = "b", alpha = 0.5) +
  theme_classic()

DicaSugestão, use o pacote gratia

Existe um pacote excelente chamado gratia (criado por Gavin Simpson), feito especificamente para traduzir modelos do mgcv para a linguagem do ggplot2 ( Figura 1.5).

Código
pacman::p_load(gratia)

modelo <- gam(mpg ~ s(hp) + s(wt), data = mtcars)
draw(modelo)
Figura 1.5: Gráfico do modelo gam usando pacote gratia
  • aov(): Análise de Variância (ANOVA). Matematicamente equivalente a um modelo linear com preditores categóricos, mas focado na variância entre grupos. Utilize para comparar médias de três ou mais grupos. Use TukeyHSD() depois para ver onde estão as diferenças.
Código
# ANOVA de uma via
anova_res <- aov(Petal.Length ~ Species, data = iris)
summary(anova_res)
             Df Sum Sq Mean Sq F value Pr(>F)    
Species       2  437.1  218.55    1180 <2e-16 ***
Residuals   147   27.2    0.19                   
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
DicaUse o pacote broom

Assim como na regressão, o summary(anova_res) retorna um objeto difícil de manipular ou não profissionalmente formatado e o gtsummary foca mais em coeficientes de regressão, para a Tabela de ANOVA (aquela com Soma de Quadrados, GL, F), a melhor combinação é limpar com broom e formatar com flextable ou gt.

Código
anova_res <- aov(mpg ~ factor(cyl) + factor(gear), data = mtcars)

# Transforma a saída feia do console em um data frame organizado
tabela_limpa <- tidy(anova_res)

gt(tabela_limpa)
term df sumsq meansq statistic p.value
factor(cyl) 2 824.784590 412.392295 38.000627 1.412658e-08
factor(gear) 2 8.251855 4.125927 0.380191 6.873334e-01
Residuals 27 293.010743 10.852250 NA NA
DicaPacote effectsize

Atualmente, apresentar apenas o valor-p da ANOVA é considerado insuficiente. Você deve apresentar o tamanho do efeito (\(\eta^2\) ou Partial Eta Squared). O pacote effectsize (da família easystats) faz isso e já formata para você.

Código
pacman::p_load(effectsize)

# Calcula Eta Squared e já formata a tabela
eta_squared(anova_res, partial = FALSE) %>%
  as.data.frame() %>%
  gt() # ?effectsize para mais informações
Parameter Eta2 CI CI_low CI_high
factor(cyl) 0.732460060 0.95 0.5667547 1
factor(gear) 0.007328161 0.95 0.0000000 1
  • predict(): Função genérica para gerar valores previstos usando um modelo ajustado (lm, glm, etc.) em novos dados. Utilize para aplicar seu modelo treinado em um conjunto de teste ou novos dados reais.
Código
# Prevê probabilidades para novos clientes (Regressão Logística)
previsoes <- predict(mod_log, newdata = novos_clientes, type = "response")
DicaPacote finalfit

Rápido e muito técnico também

Código
pacman::p_load(finalfit, dplyr, ggplot2,Hmisc)

explanatory = c("age.factor", "sex.factor", 
  "obstruct.factor", "perfor.factor")
dependent = 'mort_5yr'
colon_s %>%
  or_plot(dependent, explanatory)

Extraindo informações dos modelos:

  • coef(modelo): Extrai os coeficientes estimados.
  • residuals(modelo): Extrai os resíduos.
  • anova(modelo): Tabela de análise de variância.
  • AIC(modelo): Critério de informação de Akaike.
DicaRecomendação Especial: GLM

Aos interessados em dominar Modelos Lineares Generalizados (GLM), deixo minha forte recomendação para a disciplina MAE5763-Modelos Lineares Generalizados. Ela é oferecida no segundo semestre no IME-USP e ministrada pelo Professor Gilberto Alvarenga Paula. Pela profundidade e didática, considero esta uma das disciplinas mais valiosas da minha formação.

1.17 Visualização de Dados

Gráficos doR Base

Úteis para inspeção rápida de dados.

  • plot(x, y): Função genérica e polimórfica que adapta o gráfico dependendo do tipo de objeto fornecido. Se receber dois vetores numéricos, cria um gráfico de dispersão ( Figura 1.6); se receber um fator e um numérico, cria boxplots. A ferramenta universal para uma primeira olhada na relação entre duas variáveis \((X \times Y)\) ou para visualizar objetos complexos (como resíduos de um modelo linear plot(modelo)).
Código
plot(x = mtcars$wt, y = mtcars$mpg, 
     main = "Peso vs Consumo", xlab = "Peso", ylab = "MPG", pch = 19)
Figura 1.6: Gráfico de dispersão (Scatterplot) entre Peso (wt) e Consumo (mpg)
  • hist(x): Divide uma variável numérica contínua em intervalos (bins) e conta a frequência de observações em cada um ( Figura 1.7). Utilize para entender a distribuição dos dados: verificar normalidade, assimetria (skewness) ou identificar se a distribuição é bimodal.
Código
hist(iris$Petal.Length, xlab = "Petal.Length",
     col = "lightblue", main = "Distribuição das Pétalas", breaks = 10)
Figura 1.7: Histograma do comprimento das pétalas
  • boxplot(x): Representação visual do resumo de cinco números: mínimo, 1º quartil, mediana, 3º quartil e máximo ( Figura 1.8). Pontos fora dos “bigodes” indicam outliers. A melhor ferramenta para comparar distribuições entre diferentes grupos e detectar anomalias (outliers) rapidamente. Aceita sintaxe de fórmula (y ~ grupo).
Código
boxplot(len ~ supp, data = ToothGrowth, 
        col = c("orange", "yellow"), main = "")
Figura 1.8: Tamanho do dente por tipo de suplemento (ToothGrowth)
  • barplot(height): Cria barras com alturas proporcionais aos valores fornecidos ( Figura 1.9).
ImportanteAtenção

Diferente do histograma, ele exige que você forneça um vetor ou matriz de contagens/valores já sumarizados (ex: resultado de table()). Utilize para comparar quantidades entre categorias discretas.

Código
contagem <- table(mtcars$cyl)
barplot(contagem, xlab="Número de carros",
        main = "", col = "steelblue", ylab = "Número de cilindros")
Figura 1.9: Contagem de carros por número de cilindros
  • pairs(df): Cria uma matriz de scatterplots, cruzando todas as variáveis numéricas do dataframe umas contra as outras (N x N). Essencial na fase inicial de Análise Exploratória (EDA) multivariada para detectar correlações lineares, clusters naturais ou padrões entre múltiplas variáveis simultaneamente ( Figura 1.10).
Código
pairs(iris[, 1:4], 
      col = iris$Species, pch = 1, main = "")
Figura 1.10: Matriz de dispersão das 4 variáveis numéricas do iris
  • abline(): Adiciona linhas retas (horizontais, verticais ou regressão) a um gráfico existente. Útil para adicionar a linha de tendência.
Código
plot(mtcars$wt, mtcars$mpg, xlab = "wt", ylab="mpg")
abline(lm(mpg ~ wt, data = mtcars), col = "red") # Adiciona linha de regressão

Elementos de Baixo Nível

  • points(x, y): Adiciona símbolos (pontos) a um gráfico já aberto. Permite sobrepor novas séries de dados ou destacar pontos específicos com cores/formatos diferentes. Utilize para destacar outliers, adicionar uma segunda variável no mesmo eixo Y ou marcar médias sobre um boxplot ( Figura 1.11).
Código
plot(mtcars$wt, mtcars$mpg, xlab = "wt", ylab = "mpg")
points(mtcars$wt[mtcars$cyl == 8], mtcars$mpg[mtcars$cyl == 8], col = "red", pch = 19)
Figura 1.11: Adicionando pontos vermelhos para carros com 8 cilindros
  • lines(x, y): Conecta coordenadas (x, y) com segmentos de linha.
Importante

Atenção: Os dados devem estar ordenados pelo eixo X, senão a linha ficará “rabiscada”. Utilize para desenhar séries temporais, curvas de modelos ajustados (suavizações) ou polígonos de contorno ( Figura 1.12).

Código
plot(pressure$temperature, pressure$pressure, xlab = "temperature", ylab="pressure")
lines(pressure$temperature, pressure$pressure, col = "blue", lwd = 2)
Figura 1.12: Conectando os pontos com uma linha azul
  • abline(a, b): Adiciona linhas retas de referência que atravessam todo o gráfico. Pode ser horizontal (h), vertical (v) ou baseada em intercepto e inclinação (a, b). Ideal para adicionar a linha de regressão (abline(modelo)), linhas de média (horizontal) ou limites de especificação/datas importantes (vertical) ( Figura 1.13).
Código
plot(mtcars$wt, mtcars$mpg, xlab = "wt", ylab = "mpg")
abline(h = mean(mtcars$mpg), col = "red"); abline(v = 3, col = "green")
Figura 1.13: Adiciona linha horizontal na média (vermelha) e vertical em x=3 (verde)
  • text(x, y, labels): Plota strings de texto dentro da área do gráfico nas coordenadas (x, y) especificadas. Utilize para rotular pontos de dados individuais (ex: nome do país no scatterplot) ou anotar equações e valores-p ( Figura 1.14).
Código
plot(mtcars$wt, mtcars$mpg, xlab = "wt", ylab = "mpg")
text(x = max(mtcars$wt)-2, y = min(mtcars$mpg)+3, labels = "Carro Mais Pesado", pos = 2)
Figura 1.14: Escreve o nome do carro no ponto mais pesado
  • legend(x, y, legend): Adiciona uma caixa de legenda explicando o significado das cores, símbolos ou tipos de linha ( Figura 1.15). Essencial sempre que você usar cores ou tipos de linha diferentes para representar grupos, pois o R Base não cria legendas automáticas (ao contrário do ggplot2).
Código
# O dataset iris tem 3 espécies. Vamos criar um vetor de 3 cores.
minhas_cores <- c("red", "blue", "forestgreen")

#Criar o gráfico base
plot(x = iris$Sepal.Length, 
     y = iris$Sepal.Width,
     col = minhas_cores[iris$Species], 
     pch = 19, # Bolinha sólida
     main = "",
     xlab = "Comprimento",
     ylab = "Largura")

#Adicionar a legenda
legend("topright", 
       legend = levels(iris$Species), # Pega os nomes reais: setosa, versicolor...
       col = minhas_cores,            # Usa AS MESMAS cores definidas acima
       pch = 19,                      # Usa O MESMO símbolo do plot
       title = "Espécies",
       bty = "n")                     #Remove a caixa em volta da legenda
Figura 1.15: Sépala: Comprimento vs Largura

Parâmetros Gráficos (par): Configuram o dispositivo gráfico globalmente.

  • par(mar = c(bottom, left, top, right)): Define as margens da figura na ordem: Baixo, Esquerda, Cima, Direita. A unidade é “linhas de texto”. O padrão é c(5, 4, 4, 2) + 0.1. Utilize quando os rótulos dos eixos são cortados ou quando você precisa de espaço extra fora do gráfico para uma legenda externa ( Figura 1.16).
Código
# Gráfico 1: Margens padrão
# O texto longo no eixo X será cortado
barplot(1:5, 
        names.arg = c("Nome Muito Longo 1", "Nome Muito Longo 2", "...", "...", "..."), 
        las = 2,
        main = "Margem Padrão")

# Gráfico 2: Margens ajustadas
# par(mar = c(baixo, esquerda, cima, direita))
# Aumentamos o primeiro valor (baixo) de ~5 para 10
par(mar = c(10, 4, 4, 2))

barplot(1:5, 
        names.arg = c("Nome Muito Longo 1", "Nome Muito Longo 2", "...", "...", "..."), 
        las = 2,
        main = "Margem Ajustada")
(a) Sem aumentar as margens (Corta o texto)
(b) Aumentando as margens (Texto visível)
Figura 1.16: Ajuste de margens em barplots
  • par(mfrow = c(rows, cols)): Cria uma grade (matriz) para plotar múltiplos gráficos na mesma janela. c(linhas, colunas). Utilize para comparar visualizações lado a lado (ex: um histograma ao lado de um boxplot da mesma variável).
Código
par(mfrow = c(1, 2)) # Prepara grade 1 linha x 2 colunas
hist(mtcars$mpg, xlab="", ylab="", main="")
boxplot(mtcars$mpg, xlab="", ylab="", main="") # Plota os dois

Código
par(mfrow = c(1, 1)) # Restaura para 1 gráfico por vez
  • par(usr): Retorna (ou define) os limites extremos das coordenadas do gráfico no formato c(x1, x2, y1, y2). Utilize para saber exatamente onde terminam os eixos para posicionar textos nos cantos absolutos da figura, independente dos dados.
Código
plot(1:10)

Código
limites <- par("usr") # Retorna ex: c(0.64, 10.36, 0.64, 10.36)
# Use o limite superior do eixo Y para posicionar algo no topo
  • strheight(), strwidth(): Calcula quanto espaço (nas coordenadas do usuário) uma string de texto vai ocupar. Utilize para posicionar legendas personalizadas exatamente “ao lado” de um ponto sem sobrepor, ou para desenhar caixas ao redor de textos manualmente.
Código
plot(1:10)
largura <- strwidth("Meu Texto")
# Desenha uma linha exatamente do tamanho do texto
segments(x0=1, y0=5, x1=1+largura, y1=5)

Importanteggplot2

Um pacote muito bom e completo para questões de visualização gráfica

1.18 Visualização Profissional de Dados com ggplot2

O pacote ggplot2, implementação da Gramática dos Gráficos, que constrói visualizações complexas sobrepondo camadas lógicas independentes. Foca no mapeamento de dados em atributos visuais, permitindo flexibilidade total sem precisar memorizar dezenas de funções isoladas. Clique aqui para se informar melhor.

1.18.1 Estrutura fundamental

Todo gráfico necessita de três componentes mínimos:

  1. Dados (Data): O data frame contendo as informações brutas e variáveis que alimentarão o gráfico. É a base fundamental que permanece inalterada, servindo de fonte para todas as camadas visuais subsequentes.
  2. Estética (Aesthetics - aes): O que representa o eixo X?, o eixo Y? a cor?, etc. Mapeia colunas de dados para propriedades visuais do gráfico (como eixos X/Y, cores ou tamanhos). Define “o quê” será mostrado e como as variáveis controlarão a aparência dinâmica dos elementos.
  3. Geometria (Geoms): Qual a forma visual (barra, ponto, linha)?. É o objeto visual escolhido para representar os dados na tela, definindo a forma do gráfico (ex: barras, pontos, linhas).
  • Template Universal /"A Anatomia do ggplot"

O ggplot2 funciona através da sobreposição de camadas (layers) conectadas pelo sinal de +.

Importante

A ordem importa, o que vem depois é desenhado por cima do anterior.

ggplot(
  data = <DADOS>, 
  mapping = aes(x = <VAR_X>, y = <VAR_Y>, color = <VAR_GRUPO>, fill = <VAR_PREENCHIMENTO>)
) +
  
#1. GEOMETRIAS (A forma visual) ---
# Podem herdar os aes() globais ou ter os seus próprios
<GEOM_FUNÇÃO>(
  mapping = aes(...),           # Mapeamento específico desta camada
  data = <DADOS_FILTRADOS>,     # Usar dados diferentes nesta camada
  stat = "<ESTATÍSTICA>",       # Transformação estatística (ex: "identity", "count")
  position = "<POSIÇÃO>",       # Ajuste de sobreposição (ex: "dodge", "jitter", "stack")
  alpha = 0.5,                  # Transparência fixa (não mapeada)
  size = 2                      # Tamanho fixo
) +

#2. ESTATÍSTICAS
# Útil quando você quer resumir dados (ex: média e erro) sem pré-calcular
stat_summary(fun = mean, geom = "point") +
stat_smooth(method = "lm") +

#FACETAS (Small Multiples)
# Dividir em sub-gráficos
facet_wrap(~ <VAR_CATEGORIA>, scales = "free_y") +  # Ou facet_grid(l ~ c)

#ESCALAS (O controle fino dos mapeamentos)
# Controlam eixos (limites, log), cores, tamanhos e formatos
scale_x_continuous(limits = c(0, 100), breaks = seq(0, 100, 10)) +
scale_y_log10() +
scale_color_manual(values = c("red", "blue", "green")) + # Cores personalizadas
scale_fill_viridis_d() +                                 # Paletas prontas

#COORDENADAS (O espaço do gráfico)
# Inverter eixos, fixar proporção, mapas ou polar
coord_flip() +           # Deita o gráfico (x vira y)
# coord_cartesian(ylim = c(0, 50)) + # Zoom sem cortar dados
# coord_fixed(ratio = 1) +           # Garante proporção 1:1

#RÓTULOS E ANOTAÇÕES
labs(
  title = "Título Principal",
  subtitle = "Subtítulo explicativo",
  caption = "Fonte: Base de dados X",
  x = "Rótulo Eixo X",
  y = "Rótulo Eixo Y",
  color = "Título da Legenda de Cor",
  tag = "Fig. A" # Atribui letra de identificação a figura, 
                 #casos em em vai colocar dois ou mais graficos e quer identificar-os pode letra
) +

# Adicionar texto/setas manuais soltos no gráfico
annotate("text", x = 10, y = 50, label = "Ponto Crítico", color = "red") +

# GUIAS (Customização das Legendas)
# Ajustes finos na aparência das legendas (remover, mudar linhas, etc)
guides(
  color = guide_legend(override.aes = list(size = 5)), # Aumenta bolinha na legenda
  fill = "none" # Remove a legenda de preenchimento
) +

# TEMA (Aparência Geral)
theme_minimal(base_size = 14) +  # Comece com um tema pronto

# AJUSTES DE TEMA (Personalização final)
# Sobrescreve detalhes do tema escolhido acima
theme(
  legend.position = "top",             # Posição da legenda (top, bottom, left, right, none)
  plot.title = element_text(face = "bold", hjust = 0.5), # Título centralizado e negrito
  axis.text.x = element_text(angle = 45, hjust = 1),     # Rotação do texto do eixo X
  panel.grid.minor = element_blank()   # Remove grades menores
)

Mapeamento vs. Configuração

A maior fonte de erros para iniciantes e intermediários é a distinção entre estar dentro ou fora do aes().

Importanteaes()
  • Dentro do aes() (Mapeamento): Conecta uma variável dos dados a uma propriedade visual, fazendo a aparência mudar dinamicamente conforme o valor (ex: cores diferentes para espécies diferentes). O ggplot2 cria automaticamente uma legenda para explicar essa relação entre dado e visual.
    • Ex: aes(color = Species) - “A cor muda conforme a Espécie”.
  • Fora do aes() (Configuração): Aplica um estilo fixo e uniforme a todos os elementos da geometria, ignorando os valores dos dados (ex: pintar todos os pontos de azul). Não gera legenda, pois define apenas uma constante estética sem vínculo estatístico.
    • Ex: geom_point(color = "blue") - “Todos os pontos são azuis”.

1.18.2 Geometrias (Geoms)

Definem a forma do gráfico.

Caso Univariado (Uma Variável)

A. Para Variáveis Contínuas (Números Reais)

Ex: Salário, Idade, Temperatura, Altura.

  1. geom_histogram() Figura 1.17

    • Divide os dados em compartimentos (bins) e conta a frequência. Útil para visualização da distribuição dos dados.
    • Parâmetros Chave: binwidth (largura do intervalo) ou bins (quantidade de barras). Sempre teste larguras de bins diferentes; a escolha padrão (30) raramente é a ideal.
Código
pacman::p_load(ggplot2)
ggplot(diamonds, aes(x = price)) +
  geom_histogram(binwidth = 1000, fill = "dodgerblue", color = "white") +
  theme_minimal()
Figura 1.17: Histograma do Preço de Diamantes
  1. geom_density() Figura 1.18

    • Estima a Função Densidade de Probabilidade (KDE). É um histograma “suavizado”. Útil quando você quer ver a forma da distribuição sem o ruído das barras.
    • Parâmetros Chave: adjust (suavização: <1 é detalhado, >1 é liso), alpha (transparência).
Código
ggplot(diamonds, aes(x = price, fill = cut)) +
  geom_density(alpha = 0.5) +
  theme_minimal()
Figura 1.18: Densidade suavizada
  1. geom_freqpoly() Figura 1.19

    • Calcula o mesmo que o histograma, mas desenha linhas conectando os topos das barras em vez das barras em si. Ideal para comparar distribuições de vários grupos sobrepostos (onde histogramas ficariam bagunçados).
Código
ggplot(diamonds, aes(x = price, color = cut)) +
  geom_histogram(binwidth = 1000) + #barras histograma
  geom_freqpoly(binwidth = 1000) + #linhas 
  theme_minimal()
Figura 1.19: Polígono de frequência comparando cortes
  1. geom_dotplot() Figura 1.20

    • Empilha um ponto para cada observação. É ótimo para conjuntos de dados pequenos (\(N < 100\)) onde você quer mostrar cada indivíduo.
ImportanteAtenção

Requer binaxis = "x" e stackdir = "center" ou "up" para funcionar bem como univariado.

Código
ggplot(mtcars, aes(x = mpg)) +
  geom_dotplot(binaxis = "x", stackdir = "center", dotsize = 0.7) +
  theme_minimal() # Remove eixos para focar nos pontos
Figura 1.20: Dotplot do consumo de combustivel
  1. stat_ecdf() (ou geom_step) Figura 1.21

    • Função de Distribuição Acumulada Empírica. Útil para pesponder perguntas como “Qual porcentagem dos meus dados está abaixo do valor X?”. É a visualização mais estatisticamente íntegra, pois não depende de bins ou suavização.
Código
ggplot(diamonds, aes(x = price)) +
  stat_ecdf(geom = "step", color = "darkred") +
  labs(y = "Probabilidade Acumulada") +
  theme_minimal()
Figura 1.21: Distribuição Acumulada
  1. geom_rug() Figura 1.22

    • Desenha pequenos riscos (tiques) nas margens dos eixos para cada dado existente (Veja eixo X da Figura 1.22 e Figura 1.5). Usado como complemento em histogramas ou densidades para mostrar onde estão os dados reais, especialmente para identificar outliers ou clusters.
Código
ggplot(mtcars, aes(x = wt)) +
  geom_density(fill = "gray90") +
  geom_rug(sides = "b", length = unit(0.2, "cm")) + # 'b' = bottom (embaixo)
  theme_minimal()
Figura 1.22: Densidade com Rug Plot na base

B. Para Variáveis Discretas (Categorias)

Ex: Espécie, País, Mês, Sim/Não.

  1. geom_bar() Figura 1.23

    • Conta quantas linhas existem para cada categoria. O R faz o trabalho de contar por você. Útil quando você tem a lista bruta de dados (ex: uma planilha com 1000 linhas onde a coluna “Estado” repete SP, MG, RJ várias vezes).
    • Stat Padrão: count (o R calcula a contagem).
    • Parâmetros Chave: fill (cor interna das barras), width (largura das barras).
Código
ggplot(mtcars, aes(x = factor(cyl))) +
  geom_bar(fill = "steelblue") +
  theme_minimal()
Figura 1.23: Contagem automática de carros por cilindro
  1. geom_col() Figura 1.24

    • Desenha barras com alturas baseadas em valores numéricos que já existem na sua tabela. Útil quando você já tem o resumo pronto (ex: uma tabela pequena com apenas 3 linhas: SP=500, MG=300, RJ=200).
    • Stat Padrão: identity (o R usa o valor exatamente como ele é).
Código
# Criando uma tabela resumo fictícia
resumo <- data.frame(fruta = c("Maçã", "Banana"), valor = c(20, 30))

ggplot(resumo, aes(x = fruta, y = valor)) +
  geom_col(fill = "orange") +
  theme_minimal()
Figura 1.24: Barras com valores pré-definidos
DicaBar vs Col
  • Use geom_bar() se você tiver dados brutos e quiser que o R conte.
  • Use geom_col() se você já tiver uma tabela resumo com os totais.

C. Gráficos de Resumo e Distribuição (Pseudo-Univariados)

Embora geralmente usados para comparar grupos (Bivariados), eles são excelentes para analisar uma única variável numérica se você mapear x = "" ou x = 1.

  1. geom_boxplot() Figura 1.25

    • O diagrama de caixa. Mostra a Mediana (linha central), o Intervalo Interquartil (a caixa, de 25% a 75%) e os outliers (pontos além dos bigodes). Útil para para detectar valores extremos, distribuição, assimetria, etc.
    • Parâmetros Chave: outlier.color (destacar os outliers), notch = TRUE (adiciona um entalhe na mediana para comparação visual de significância).
Código
ggplot(mtcars, aes(x = factor(cyl), y = hp)) +
  geom_boxplot(outlier.color = "red", outlier.shape = 8) +
  theme_bw()
Figura 1.25: Boxplot da potência por cilindro
  1. geom_violin() Figura 1.26

    • Um espelhamento do geom_density (densidade) rotacionado em 90 graus. Mostra a forma completa da distribuição de maneira compacta. É mais rico que o boxplot porque revela se a distribuição é bimodal (tem “duas corcovas”), algo que o boxplot esconde.
    • Parâmetros Chave: draw_quantiles (desenha linhas nos quartis dentro do violino).
Código
ggplot(diamonds[1:500,], aes(x = cut, y = price)) +
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75), fill = "lightblue") +
  theme_classic()
Figura 1.26: Violin plot comparando distribuições
  1. geom_jitter() Figura 1.27

    • Adiciona um pequeno ruído aleatório aos pontos para evitar sobreposição (overplotting). Frequentemente usado por cima do geom_boxplot() para mostrar os dados brutos reais junto com o resumo estatístico.
    • Parâmetros Chave: width e height (controlam o quanto os pontos podem “tremer”).
Código
ggplot(mtcars, aes(x = factor(cyl), y = hp)) +
  geom_boxplot(alpha = 0.3) +
  geom_jitter(width = 0.2, color = "darkblue") + # width controla a 'tremida' horizontal
  theme_minimal()
Figura 1.27: Boxplot + Jitter (Dados brutos)

Bivariada: Contínua X Contínua Ex: Peso vs Altura, Preço vs Quilometragem.

  1. geom_point() Figura 1.28
    • O clássico gráfico de dispersão (Scatterplot). Mostra a relação exata entre duas variáveis.
Código
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point(size = 3, color = "darkgreen") +
  theme_minimal()
Figura 1.28: Scatterplot clássico
  1. geom_jitter() Figura 1.29

  2. geom_smooth()

    • Adiciona uma linha de tendência (regressão linear, LOESS, GAM). Ajuda o olho a ver o padrão no meio dos pontos.
Código
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  geom_smooth(method = "lm", se = TRUE, color = "red") + # se=TRUE mostra intervalo de confiança
  theme_minimal()
Figura 1.29: Scatterplot com linha de tendência linear
  1. geom_quantile() Figura 1.30
    • Regressão quantílica. Em vez da média (como o smooth), mostra tendências para os 25%, 50% e 75% mais extremos.
Código
ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(alpha = 0.3) +
  
  # Regressão Linear (Média) em Vermelho para comparação
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  
  # Regressão Quantílica (25%, 50%, 75%) em Azul
  geom_quantile(quantiles = c(0.25, 0.5, 0.75), color = "blue", size = 1) +
  
  theme_minimal() +
  labs(title = "Tendências dos Extremos vs Média",
       subtitle = "Azul: Quantis (0.25, 0.50, 0.75) | Vermelho: Média (LM)")
Figura 1.30: Regressão Quantílica (25%, 50%, 75%) vs Regressão Linear (Vermelho)
  1. geom_text() e geom_label() Figura 1.31
    • Escrevem texto no gráfico nas coordenadas X e Y.
    • Diferença: geom_label desenha uma caixinha colorida atrás do texto para facilitar a leitura; geom_text desenha apenas as letras.
Código
df <- data.frame(x = c(1, 3), y = c(1, 1), texto = c("Texto Puro", "Etiqueta"))

ggplot(df, aes(x = x, y = y, label = texto)) +
  xlim(0, 4) + ylim(0, 2) +
  # Lado Esquerdo: Texto solto
  geom_text(data = subset(df, x == 1), size = 6) +
  # Lado Direito: Texto dentro da caixinha
  geom_label(data = subset(df, x == 3), size = 6, fill = "white") +
  theme_bw()
Figura 1.31: Diferença entre geom_text e geom_label
  1. geom_bin2d() e geom_hex() Figura 1.32
    • Quando você tem milhões de pontos, o scatterplot vira uma mancha preta. Estes geoms dividem o plano em quadrados (bin2d) ou hexágonos (hex) e pintam a cor baseada na contagem de pontos naquela região (mapa de calor 2D).
Código
pacman::p_load(hexbin)

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_hex(bins = 30) +
  scale_fill_viridis_c() +
  theme_minimal()
Figura 1.32: Mapa de calor hexagonal (Hexbin)

Bivariada: Discreta X Contínua

Ex: Grupo (A, B) vs Nota.

Além dos já citados geom_boxplot, geom_violin e geom_col:

  1. geom_dotplot(binaxis = "y") Figura 1.33
    • Semelhante ao violino, mas feito de bolinhas empilhadas.
Código
ggplot(mtcars, aes(x = factor(cyl), y = mpg, fill = factor(cyl))) +
  # binaxis = "y" faz as bolinhas subirem no eixo Y
  # stackdir = "center" empilha elas para os dois lados (parece um violino)
  geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.8) +
  theme_minimal() +
  theme(legend.position = "none") # Remove a legenda pois a cor já indica os cilindros
Figura 1.33: Dotplot Bivariado: Distribuição do consumo por cilindros

1.18.3 Séries Temporais e Funções (Evolução)

Ex: Data no Eixo X.

  1. geom_line() Figura 1.34
    • Conecta os pontos na ordem da variável X. Padrão para séries temporais.
Código
economics |> 
  ggplot(aes(x = date, y = unemploy)) +
  geom_line(color = "blue") +
  theme_minimal()
Figura 1.34: Série temporal simples
  1. geom_path() Figura 1.35
    • Conecta os pontos na ordem em que aparecem na tabela (mesmo que o X volte para trás). Usado para desenhar trajetórias em mapas ou formas complexas.
Código
# Note que a linha faz voltas e loops, o que seria impossível com geom_line()
# geom_path conecta os dados cronologicamente
ggplot(economics, aes(x = uempmed, y = psavert)) +
  geom_path(color = "purple") +
  labs(
    title = "Trajetória Econômica (1967-2015)",
    subtitle = "A linha conecta os pontos na ordem cronológica",
    x = "Duração do Desemprego (Mediana)",
    y = "Taxa de Poupança Pessoal"
  ) +
  theme_minimal()
Figura 1.35: Geom Path: Ciclo Econômico (Desemprego vs Poupança)
  1. geom_step() Figuar Figura 1.36
    • Gráfico de “escada”. A linha só muda de nível abruptamente. Bom para visualizar taxas de juros ou estoques que mudam em saltos.
Código
# Criando dados fictícios de uma taxa que muda pouco
dados_step <- data.frame(
  mes = 1:12,
  taxa = c(2, 2, 2, 5, 5, 5, 5, 3, 3, 6, 6, 6)
)

ggplot(dados_step, aes(x = mes, y = taxa)) +
  geom_step(color = "darkblue", size = 1) +
  geom_point(color = "red") + # Adicionando pontos para mostrar quando a medição ocorreu
  labs(title = "Evolução da Taxa (Gráfico de Escada)") +
  scale_x_continuous(breaks = 1:12) +
  theme_bw()
Figura 1.36: Geom Step: Mudanças na Taxa de Juros (Simulado)
  1. geom_area() Figura 1.37
    • Um gráfico de linha onde a área abaixo dela (até o 0) é preenchida.
Código
economics |> 
  ggplot(aes(x = date, y = unemploy)) +
  geom_area(fill = "lightblue", alpha = 0.6) +
  theme_minimal()
Figura 1.37: Gráfico de área
  1. geom_ribbon() Figura 1.38
    • Desenha uma faixa colorida entre um valor mínimo (ymin) e máximo (ymax). Fundamental para desenhar Intervalos de Confiança ao redor de uma linha.
Código
# Criando dados fictícios de previsão
df_ribbon <- data.frame(
  ano = 2000:2010,
  valor = 10:20,
  min = (10:20) - 2,
  max = (10:20) + 2
)

ggplot(df_ribbon, aes(x = ano, y = valor)) +
  geom_ribbon(aes(ymin = min, ymax = max), fill = "grey80") +
  geom_line() +
  theme_minimal()
Figura 1.38: Ribbon (faixa) ao redor de uma linha

Visualização de Incerteza e Erro Ex: Médias com desvio padrão.

  1. geom_errorbar() Figura 1.39
    • A clássica barra de erro (formato “I”).
Código
df_erro <- data.frame(grp = c("A", "B"), media = c(10, 15), sd = c(1, 2))

p1 <- ggplot(df_erro, aes(x = grp, y = media)) +
  geom_point() +
  geom_errorbar(aes(ymin = media-sd, ymax = media+sd), width = 0.2) +
  ggtitle("Errorbar")+
  theme_minimal()

p2 <- ggplot(df_erro, aes(x = grp, y = media)) +
  geom_pointrange(aes(ymin = media-sd, ymax = media+sd)) +
  ggtitle("Pointrange")+
  theme_minimal()

pacman::p_load(patchwork)
p1 + p2
Figura 1.39: Barras de erro e Pointrange
  1. geom_linerange() Figura 1.40
    • Uma linha vertical simples indicando o intervalo (sem os traços horizontais nas pontas). Visual mais limpo.
Código
dados_erro <- data.frame(
  grupo = c("Controle", "Tratamento A", "Tratamento B"),
  media = c(20, 25, 18),
  min = c(18, 23, 15),
  max = c(22, 27, 21)
)

ggplot(dados_erro, aes(x = grupo, y = media)) +
  # O linerange desenha apenas a linha vertical
  geom_linerange(aes(ymin = min, ymax = max), size = 1.2, color = "gray50") +
  # Adicionamos o ponto separadamente para marcar a média
  geom_point(size = 4, color = "blue") +
  theme_minimal() +
  labs(title = "Geom Linerange + Point")
Figura 1.40: Linerange: Intervalo limpo (Min-Max)
  1. geom_pointrange() Figura 1.41
    • Combina um ponto (média) e uma linha vertical (intervalo) em um único geom geométrico. Muito usado em Forest Plots.
Código
ggplot(dados_erro, aes(x = grupo, y = media)) +
  # ymin e ymax são obrigatórios aqui
  geom_pointrange(aes(ymin = min, ymax = max), color = "darkred") +
  coord_flip() + # Forest plots geralmente são deitados
  theme_bw() +
  labs(title = "Geom Pointrange (Invertido)")
Figura 1.41: Pointrange: O padrão para Forest Plots
  1. geom_crossbar() Figura 1.42
    • Uma caixa vazia ou preenchida representando o intervalo, com uma linha na média.
Código
ggplot(dados_erro, aes(x = grupo, y = media)) +
  geom_crossbar(
    aes(ymin = min, ymax = max), 
    width = 0.5, 
    fill = "lightblue", 
    alpha = 0.5
  ) +
  theme_minimal() +
  labs(title = "Geom Crossbar")
Figura 1.42: Crossbar: Intervalo como caixa sólida

Três Variáveis (Mapas de Calor e Contornos)

Ex: Z = Altitude, variando em X (Lat) e Y (Long).

  1. geom_tile() e geom_raster() Figura 1.43
    • Criam superfícies ou mapas de calor (heatmaps). geom_raster é uma versão otimizada de geom_tile para quando todos os quadrados têm o mesmo tamanho (renderiza mais rápido).
Código
# Matriz de correlação transformada em formato longo
cormat <- as.data.frame(as.table(cor(mtcars)))

ggplot(cormat, aes(Var1, Var2, fill = Freq)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white") +
  theme_minimal()
Figura 1.43: Heatmap (Mapa de Calor)
  1. geom_contour() e geom_contour_filled() Figura 1.44
    • Desenha linhas de contorno (como em mapas topográficos) baseadas na variável Z.
Código
pacman::p_load(reshape2)
volcano_df <- melt(volcano)
names(volcano_df) <- c("x", "y", "z")

ggplot(volcano_df, aes(x, y, z = z)) +
  # Preenchimento das regiões (o visual colorido)
  geom_contour_filled() +
  # Linhas pretas finas para demarcar 
  geom_contour(color = "black", size = 0.1) +
  theme_void() + # Remove eixos para parecer um mapa
  coord_fixed()
Figura 1.44: Topografia do Vulcão Maunga Whau (Contour Filled)

Mapas e Espacial{#sec-espacial_visualizacao}

  1. geom_sf() Figura 1.45 e Figura 1.46
    • Plota objetos Simple Features (do pacote sf). Lida automaticamente com projeções geográficas, fronteiras de países e coordenadas.
Código
pacman::p_load(sf, ggplot2)

# Lendo um shapefile de exemplo que vem dentro do pacote sf
nc <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)

ggplot(nc) +
  geom_sf(aes(fill = AREA), color = "white") +
  scale_fill_viridis_c(name = "Área") +
  theme_minimal() +
  labs(title = "")
Figura 1.45: Mapa da Carolina do Norte (Shapefile nativo)
Código
pacman::p_load(sf, ggplot2, geodata, terra, viridis)

#Baixar dados do GADM
# country = "MOZ" (Código ISO de Moçambique)
# level = 2 (Distritos)
# path = tempdir() salva numa pasta temporária. Para salvar no projeto, use path = "."

tryCatch({
    moz_data_spat <- geodata::gadm(country = "MOZ", level = 2, path = tempdir(), version="latest")
  }, error = function(e) {
    message("Erro ao baixar do GADM. Verifique a conexão.")
    # Cria um objeto sf vazio em caso de erro para não quebrar o render
    moz_data_spat <- NULL
})


if (!is.null(moz_data_spat)) {
  #Converter de SpatVector (terra) para objeto sf
  moz_sf <- sf::st_as_sf(moz_data_spat)

  #Plotar
  ggplot2::ggplot(moz_sf) +
    geom_sf(aes(fill = NAME_1), color = "white", size = 0.1) +
    scale_fill_viridis_d(name = "Província", option = "D") + # Paleta discreta bonita
    theme_minimal() +
    theme(legend.position = "right") + # Legenda à direita
    labs(title = "",
         caption = "Fonte: Dados GADM via pacote {geodata}")

} else {
  # Mensagem alternativa no plot caso o download falhe
  ggplot2::ggplot() +
    annotate("text", x=0, y=0, label="Não foi possível baixar os dados do mapa.") +
    theme_void()
}
  • O GADM as vezes tem problemas, se não funcionou o codigo acima baixa pelo link abaixo ou vá ao site do GADM
Código
pacman::p_load(sf, ggplot2, ggrepel) 

#Se geodata não funcionar baixe os dados no link: https://drive.google.com/drive/folders/1pL_MLujCv_6h5VJqK20B8pUHSNlZ5Olt?usp=sharing

# Abra o arquivo que terá baixado no link acima caso gadm não tenha funcionado
#troque meu "/home/almonha/Downloads/Curso de Verão/moz_adm/moz_admbnda_adm1_ine_20190607.shp" pelo seu.

tryCatch({  
  moz_data_spat <- read_sf("/home/almonha/Downloads/Curso de Verão/moz_adm/moz_admbnda_adm1_ine_20190607.shp") 
  }, error = function(e) {
    message("O link não funcionou vou baixar pelo GADM.")
moz_data_spat <- geodata::gadm(country = "MOZ", level = 2, path = tempdir(), version="latest")
}) 



if (!is.null(moz_data_spat)) {
  
  moz_sf <- sf::st_as_sf(moz_data_spat)
  
  ggplot2::ggplot(data = moz_sf) +
    geom_sf(aes(fill = ADM1_PT), color = "white", size = 0.1) +
  scale_fill_viridis_d(name = "Província", option = "D") + 
  theme_minimal()+
    theme(legend.position = "right",
    axis.title = element_blank()
    )+ # Remove X e Y de forma mais limpa) + 
    labs(
      title = "Mapa de Moçambique",
      caption = "Fonte: Dados GADM via pacote {geodata}",
    )

} else {
  ggplot2::ggplot() +
    annotate("text", x=0, y=0, label="Não foi possível baixar os dados do mapa.") +
    theme_void()
}
Figura 1.46: Mapa de Moçambique - Nível Administrativo 2 (Distritos)
  1. geom_map()
    • Versão antiga para desenhar polígonos de mapas. Prefira geom_sf.

Primitivas e Referências: Usados para anotações manuais.

  1. geom_abline() , geom_hline(), geom_vline(), segue o descrito na seção Seção 1.17 .

  2. geom_segment() e geom_curve() Figura 1.47

    • Desenha linhas ou curvas de um ponto A (x, y) até um ponto B (xend, yend). Útil para setas e anotações.
Código
df_pontos <- data.frame(x = c(2, 8), y = c(2, 8), label = c("Início", "Fim"))

ggplot(df_pontos, aes(x, y)) +
  geom_point(size = 3) +
  xlim(0, 10) + ylim(0, 10) +
  # Segmento Reto com Seta
  geom_segment(aes(x = 2, y = 2, xend = 5, yend = 5), 
               arrow = arrow(length = unit(0.3, "cm")), color = "blue") +
  # Curva com Seta
  geom_curve(aes(x = 5, y = 5, xend = 8, yend = 8), 
             curvature = -0.3, arrow = arrow(), color = "red") +
  theme_bw()
Figura 1.47: Anotações com Segmentos e Curvas
  1. geom_rect() e geom_polygon() Figura 1.48
    • Desenha retângulos ou formas arbitrárias baseadas em coordenadas.
Código
ggplot(mtcars, aes(wt, mpg)) +
  # O retângulo deve vir ANTES dos pontos para ficar no fundo
  geom_rect(aes(xmin = 3, xmax = 4, ymin = 10, ymax = 25), 
            fill = "yellow", alpha = 0.05, color = NA) +
  geom_point() +
  annotate("text", x = 3.5, y = 26, label = "Zona de Atenção") +
  theme_minimal()
Figura 1.48: Destacando uma região de interesse com geom_rect
  1. geom_spoke() Figura 1.49
    • Desenha segmentos definidos por ângulo e raio (útil para campos vetoriais, como direção do vento).
Código
df_vento <- expand.grid(x = 1:10, y = 1:10)
df_vento$angle <- runif(100, 0, 2*pi) # Ângulo em radianos
df_vento$speed <- runif(100, 0.4, 0.8) # Comprimento do vetor

ggplot(df_vento, aes(x, y)) +
  geom_spoke(aes(angle = angle, radius = speed), arrow = arrow(length = unit(0.1, "cm"))) +
  theme_void() +
  labs(title = "")
Figura 1.49: Campo Vetorial (Direção e Intensidade Aleatórias)
  1. geom_qq() e geom_qq_line() Figura 1.50
    • Gráfico Quantil-Quantil (QQ Plot) para checar normalidade dos resíduos.
Código
ggplot(mtcars, aes(sample = mpg)) +
  geom_qq() +        # Os pontos
  geom_qq_line(color = "red") + # A linha de referência normal
  labs(title = "Os dados de MPG são normais?", 
       subtitle = "Pontos fora da linha indicam desvio da normalidade") +
  theme_minimal()
Figura 1.50: QQ Plot: Verificação de Normalidade

Faceting (Small Multiples)

A melhor técnica para evitar gráficos “espaguete” (muitas linhas misturadas).

  • facet_wrap(~variavel): Fluxo contínuo (quebra linha quando acaba espaço), Figura 1.51 .
Código
ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(alpha = 0.5) +
  # Divide o gráfico pelo tipo de carro ('class')
  # ncol = 3 força 3 colunas
  facet_wrap(~class, ncol = 3) + 
  theme_bw() +
  labs(title = "Consumo vs Motor", subtitle = "Separado por categoria (class)")
Figura 1.51: Facet Wrap: Consumo por Tipo de Carro
  • facet_grid(lin ~ col): Matriz estrita. Use . se quiser apenas uma dimensão (ex: . ~ col), Figura 1.52 .
Código
mtcars_facets <- mtcars
mtcars_facets$am <- factor(mtcars$am, labels = c("Automático", "Manual"))
mtcars_facets$cyl <- factor(mtcars$cyl, labels = c("4 Cilindros", "6 Cilindros", "8 Cilindros"))

ggplot(mtcars_facets, aes(x = wt, y = mpg)) +
  geom_point(color = "darkred") +
  # Linhas definidas pelo Câmbio (am) ~ Colunas definidas pelos Cilindros (cyl)
  facet_grid(am ~ cyl) + 
  theme_bw() +
  labs(title = "Comparação Matricial")
Figura 1.52: Facet Grid: Cruzamento de Câmbio (Linhas) vs Cilindros (Colunas)
DicaEscalas Livres

Por padrão, o ggplot2 força todos os painéis a terem a mesma escala de eixo X e Y para facilitar a comparação. Se os seus grupos têm magnitudes muito diferentes (ex: um vai até 10, outro até 1000), use o argumento scales:

  • scales = “free”: Eixos X e Y independentes.

  • scales = “free_y”: Só o Y varia.

  • scales = “free_x”: Só o X varia.

Escalas e Temas

  1. Scales (scale_*)

Controlam como os dados são mapeados visualmente.

  • Eixos: scale_x_log10(), scale_x_continuous(limits = c(0, 100), breaks = seq(0,100,10)).
  • Cores: scale_color_manual() (controle total), scale_color_viridis_d() (acessibilidade).
  1. Themes (theme)

Controlam elementos que não são dados.

  • Temas prontos: theme_bw(), theme_minimal(), theme_classic(), theme_avoid(), etc.
  • Ajuste fino: theme(legend.position = "bottom", axis.text = element_text(...)).
NotaNota sobre Extensões

O poder do ggplot2 é infinito graças aos pacotes da comunidade. Se não achou o geom aqui, provavelmente ele existe em um pacote extra:

  • ggforce: Geoms avançados (círculos, elipses, zoom).

  • ggridges: Gráficos de “Joyplot” (distribuições empilhadas).

  • ggraph: Para redes e grafos.

1.19 Extensões Essenciais do ggplot2

O poder do ggplot2 reside em suas extensões.

Rótulos Inteligentes (ggrepel)

Evita que rótulos de texto se sobreponham uns aos outros ou aos pontos. Essencial para scatterplots com nomes.

Código
pacman::p_load(ggrepel)

# Seleciona alguns carros para rotular
subset_cars <- mtcars[1:10, ]
subset_cars$car_name <- rownames(subset_cars)

ggplot(subset_cars, aes(wt, mpg, label = car_name)) +
  geom_point(color = "red") + #adiciona os pontos
  geom_text_repel() + # Afasta os textos automaticamente
  theme_classic()

Composição (patchwork)

Substitui par(mfrow) e gridExtra. Permite somar gráficos matematicamente.

Código
pacman::p_load(patchwork)
g1 <- ggplot(mtcars, aes(mpg)) + geom_histogram()+theme_classic()
g2 <- ggplot(mtcars, aes(wt, mpg)) + geom_point()+theme_classic()


(g1 | g2) / g2 +plot_annotation(title = "",tag_levels = "A") #tag_levels adiciona letras em cada grafico

Interatividade (plotly)

Transforma ggplots estáticos em HTML interativo com zoom e tooltips.

Código
pacman::p_load(plotly)
g <- ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point()
plotly::ggplotly(g)

Guardar/salvar o gráfico (ggsave)

Evite usar o botão Export da janela de plots para artigos. Ele não garante resolução (DPI) nem tamanho fixo.

Código
# Salva o último gráfico plotado
ggsave(
  filename = "figura_final.pdf", # PDF é vetorial (melhor para artigos)
  width = 10, 
  height = 6, 
  units = "in", 
  dpi = 300 # 300dpi é o padrão para impressão
)

2 Programação e Controle de Fluxo

A transição de um usuário de R “operacional” para um cientista de dados ou estatístico avançado acontece quando se deixa de rodar scripts linha a linha e passa-se a construir ferramentas robustas, automatizadas e reprodutíveis.

Estruturas Condicionais

As condicionais permitem que o código tome decisões baseadas em testes lógicos. No R, é crucial distinguir entre o controle de fluxo (escalar) e a manipulação de dados (vetorizada).

A. O if (se) e else (caso contrário) são para Controle de Fluxo

Esta estrutura controla se um bloco de código deve ser executado ou ignorado, agindo como uma “comporta” no seu script.

  • if (…): A palavra-chave que inicia o teste.

  • ( ) Parênteses: Envolvem a condição lógica. O R avalia o que está aqui dentro. Deve resultar em um único TRUE ou FALSE.

  • { } Chaves: Delimitam o bloco de código. Elas dizem ao R: “Tudo o que estiver aqui dentro pertence a este if”.

DicaPor que usar?

Sem as chaves { }, o if executaria apenas a primeira linha imediatamente abaixo dele. As chaves { } permitem agrupar dezenas de comandos (cálculos, gráficos, impressões) para serem executados juntos caso a condição seja aceita.

ImportanteRegra do Escalar

O if aceita apenas um valor lógico único. Não tente passar um vetor inteiro (ex: if (coluna > 0)), pois isso gerará um erro ou aviso. Para vetores, use ifelse().

Código
x <- 5
#  A condição (x > 0) é testada dentro dos parênteses.
if (x > 0) {                                #se x for maior que zero
  #Como é VERDADEIRO, o R entra neste bloco (entre chaves).
  #Aqui podemos ter múltiplas linhas de comando.
  print("O número é positivo.")             #imprima "O número é positivo."
} else {                                    #caso contrário
# Este bloco só rodaria se x fosse negativo ou zero.
  print("O número não é positivo.")         #imprima "O número é negativo ou zero."
}
[1] "O número é positivo."
Código
x <- 5

if (x > 0) {
  resultado <- x * 2
  print(paste("O número é positivo. O dobro é:", resultado))
} else { 
  print("O número não é positivo.")
}
[1] "O número é positivo. O dobro é: 10"
ImportanteAtenção à posição do else

No R, o else deve estar na mesma linha da chave de fechamento } do if. Se você colocá-lo na linha de baixo, o R achará que o código acabou antes e dará erro.

B. O ifelse()- A Condicional Vetorizada

Enquanto o if tradicional falha ao receber múltiplos valores, o ifelse() foi desenhado especificamente para lidar com vetores e colunas de dados inteiras de uma só vez. Ele funciona de forma análoga à função =SE() do Excel.

DicaComo funciona
  • O R verifica a condição lógica para cada elemento do vetor, criando internamente uma lista de Verdadeiro (TRUE) /Falso.
  • Para cada posição onde o teste for TRUE, ele escolhe o valor do argumento yes. Onde for FALSE, escolhe o valor do argumento no.
  • Ele retorna um novo vetor com o mesmo comprimento do original, contendo as substituições feitas.
DicaAnalogia com Excel

Pense no ifelse(coluna > 0, A, B) exatamente como a fórmula =SE(A1 > 0; "A"; "B") arrastada para todas as linhas da planilha.

Código
notas <- c(8, 4, 9, 5)
status <- ifelse(test = notas >= 7, 
                 yes = "Aprovado", 
                 no = "Reprovado")
# fluxo:
# 8 >= 7? SIM -> "Aprovado"
# 4 >= 7? NÃO -> "Reprovado"
# ... e assim por diante.
print(status)
[1] "Aprovado"  "Reprovado" "Aprovado"  "Reprovado"
Código
# Resultado: "Aprovado" "Reprovado" "Aprovado" "Reprovado"

Loops (Laços de Repetição)

Loops são usados para repetir uma tarefa múltiplas vezes.

A. for (Para cada…) — Iteração Definida

O laço for é a estrutura fundamental para repetir uma tarefa quando você sabe antecipadamente sobre o que deseja iterar. Ele percorre um vetor ou lista, elemento por elemento, executando o bloco de código para cada um deles.

  • for (...): A palavra-chave que inicia a estrutura de repetição.
  • ( var in seq ) Parênteses: Definem a regra da iteração.
  • var (ex: i): É a variável iteradora. Ela é um “placeholder” (um cursor) que assume um valor diferente a cada volta do loop.
  • in: O operador que conecta a variável à sequência. Lê-se: Para cada i DENTRO de seq.
  • seq: O vetor ou lista que será percorrido (ex: 1:10 ou c(“A”, “B”)).
  • { } Chaves: Delimitam o bloco de execução. Todo o código aqui dentro será repetido N vezes, onde N é o tamanho da sequência.

A.1 Lógica de Execução:

  1. Na 1ª volta, i assume o primeiro valor da sequência. O código entre chaves roda.

  2. Na 2ª volta, i assume o segundo valor. O código roda novamente.

  3. O processo repete até que acabem os itens da sequência.

Código
frutas <- c("Maçã", "Banana", "Uva")

for (item in frutas) {                    # Para cada 'fruta' dentro do vetor 'frutas'...
  # ... execute este bloco:
  mensagem <- paste("Eu gosto de", item)
  print(mensagem)
}
[1] "Eu gosto de Maçã"
[1] "Eu gosto de Banana"
[1] "Eu gosto de Uva"
Código
# O loop roda 3 vezes, pois há 3 frutas.
Dicaseq_along()

Ao iterar sobre um vetor, evite usar 1:length(vetor), pois se o vetor estiver vazio, isso gera um erro (gera a sequência 1:0). Prefira seq_along(vetor), que lida corretamente com vetores vazios.

Código
vetor_vazio <- c() # Criando um vetor vazio

#FORMA PERIGOSA
for (i in 1:length(vetor_vazio)) {
  print(paste("Tentando acessar o índice:", i))
}
## [1] "Tentando acessar o índice: 1"
## [1] "Tentando acessar o índice: 0"
#Resultado: "Tentando acessar o índice: 1".  O loop roda duas vezes tentando acessar dados que não existem!

#FORMA SEGURA
for (i in seq_along(vetor_vazio)) {
  print(paste("Tentando acessar o índice:", i))
}
# Resultado: "Tentando acessar o índice: 0". O loop é ignorado corretamente (silêncio total).

B. O while (Enquanto…) — Iteração Indefinida

Diferente do for, que percorre uma sequência fixa, o while é usado quando não sabemos antecipadamente quantas vezes o código precisa rodar. Ele repete o bloco de instruções indefinidamente enquanto a condição especificada for verdadeira.

  • while (...): A palavra-chave de controle.
  • ( condição ) Parênteses: Envolvem o critério de parada. O R avalia essa expressão lógica antes de cada volta. Se for TRUE, entra no loop. Se for FALSE, o loop é encerrado imediatamente.
  • { } Chaves: Delimitam o bloco de execução.
Nota

Dentro destas chaves, deve haver obrigatoriamente um comando que altere a variável testada na condição (ex: um incremento). Se a condição nunca se tornar FALSE, cria-se um loop infinito, travando a sessão do R.

Lógica de Execução

  1. Testa a condição.

  2. Se TRUE: Executa o bloco {}.

  3. Ao final do bloco, volta para o passo 1.

  4. Se FALSE: Pula o bloco e segue o script.

Código
contador <- 1
while (contador <= 3) {               # Enquanto o contador for menor ou igual a 3...
  print(paste("Contagem:", contador))
  contador <- contador + 1            # Passo Obrigatório: Atualizar a variável de controle
}
[1] "Contagem: 1"
[1] "Contagem: 2"
[1] "Contagem: 3"
Código
# Quando contador vira 4, a condição (4 <= 3) é FALSE e o loop para.
AvisoGestão de Memória: Não faça o vetor crescer

Um erro clássico é começar com um vetor vazio (x <- c()) e adicionar elementos dentro do loop (x[i] <- valor).

Por que é ruim? No R, vetores precisam de memória contígua. A cada novo elemento adicionado, o R precisa: (1) achar um novo espaço maior na memória, (2) copiar todos os dados antigos para lá, (3) adicionar o novo dado e (4) apagar o antigo. Fazer isso milhares de vezes torna o script extremamente lento (\(O(n^2)\)).

A Solução (Pré-alocação) é criar o vetor com o tamanho final desejado preenchido com zeros ou NAs.

Código
n <- 1000 # Forma Correta: Aloca memória apenas uma vez
vetor_resultado <- numeric(length = n)  #vetor vazio a ser preenchido

for (i in 1:n) {
  vetor_resultado[i] <- i * 2 # Apenas preenche a gaveta já existente
}

2.1 Funções personalizadas

Crie suas Próprias Ferramentas

O princípio DRY (Don’t Repeat Yourself — Não se Repita) defende que se você precisou copiar e colar o mesmo bloco de código mais de duas vezes, é hora de transformá-lo em uma função.

  • Uma função funciona como uma “caixa preta” ou uma pequena máquina: você insere ingredientes (argumentos), a máquina processa (corpo) e entrega um produto final (retorno).

    • nome <- function(...): Você “salva” a lógica dentro de um objeto. A partir de agora, o R reconhece esse nome como um comando executável.
    • ( arg1, arg2 = padrão ) Argumentos: São as entradas. Funcionam como variáveis temporárias que só existem dentro da função. Você pode definir valores padrão (=), que serão usados caso o usuário não informe nada naquele argumento.
  • { } Corpo: O bloco de processamento. É um “ambiente isolado” (escopo local). Variáveis criadas aqui dentro nascem e morrem aqui; elas não poluem o seu ambiente de trabalho global.

  • return(…) Retorno: A saída. Define explicitamente o que a função devolve para o usuário. Se omitido, o R retorna o resultado da última linha executada, mas usar return() torna o código mais legível.

Código
nome_da_funcao <- function(arg1, arg2 = valor_padrao) {
  soma <- arg1 + arg2
  return(soma)          # Retorno: O que sai da função
}

# Uso
resultado <- nome_da_funcao(arg1 = 10, arg2 = 5)
Código
calcular_imc <- function(peso, altura) {
  imc_valor <- peso / (altura ^ 2)              # O R recebe os valores, calcula e guarda em 'imc_valor'
  return(imc_valor)                             # Retorno: O que é enviado de volta para quem chamou
}

meu_indice <- calcular_imc(peso = 80, altura = 1.80)
print(meu_indice) # Resultado: ~24.69
[1] 24.69136
Código
# Nota: A variável 'imc_valor' não existe aqui fora. Ela morreu ao fim da função.
ImportanteEscopo Local vs. Global

Tudo o que acontece dentro das chaves {} da função fica isolado. Se você criar uma variável x <- 10 dentro da função, ela não altera uma variável x que já exista no seu ambiente global. Isso garante segurança e evita bugs.

2.2 Programação Funcional (A alternativa aos Loops)

O R é, em sua essência, uma linguagem funcional. Enquanto o loop for é imperativo (você dá ordens passo-a-passo: pegue o item 1, faça isso, salve ali), a programação funcional é declarativa (você diz o que quer: aplique esta função a todos os itens desta lista). Essa abordagem abstrai a complexidade da iteração, resultando em códigos mais limpos, legíveis e menos propensos a erros de indexação.

A. Família apply (R Base)

Este é o conjunto de funções nativas do R para iteração. São robustas e onipresentes em códigos legados e pacotes fundamentais.

  • apply(X, MARGIN, FUN): Projetada especificamente para estruturas bidimensionais (Matrizes e Data Frames). O argumento MARGIN define a direção: se for 1-aplica a função nas linhas, se for 2-aplica nas colunas.
Código
matriz <- matrix(1:9, nrow = 3)  # Criando uma matriz simples 3x3

# Aplicando apply nas LINHAS (Margin = 1) -> Soma
apply(matriz, 1, sum)  # 1+4+7, 2+5+8...
[1] 12 15 18
Código
# Aplicando apply nas COLUNAS (Margin = 2) -> Média
apply(matriz, 2, mean)
[1] 2 5 8
  • lapply(X, FUN) (List Apply): A função mais importante da família. Recebe um vetor ou lista, aplica a função a cada elemento e retorna sempre uma Lista. É a mais segura programaticamente, pois o formato de saída é previsível.
Código
números <- list(a = 4, b = 16, c = 25)

# Aplica a raiz quadrada em cada item
resultado_lista <- lapply(números, sqrt);resultado_lista
$a
[1] 2

$b
[1] 4

$c
[1] 5
Código
class(resultado_lista) # Confirma que é uma lista
[1] "list"
  • sapply(X, FUN) (Simplify Apply): Uma versão de conveniência do lapply. Ela tenta “adivinhar” o formato de saída mais simples (um vetor ou matriz) para o resultado.
Código
# A mesma operação acima, mas retornando um VETOR limpo
resultado_vetor <- sapply(números, sqrt);resultado_vetor
a b c 
2 4 5 
Código
class(resultado_vetor) # Confirma que simplificou para numérico
[1] "numeric"
ImportanteCuidado

Se a função falhar ou retornar tipos diferentes, o sapply pode devolver uma lista inesperadamente, quebrando scripts automatizados.

B. Pacote purrr (Tidyverse)

A evolução moderna da família apply. O purrr resolve o problema da imprevisibilidade do sapply introduzindo a Segurança de Tipos (Type Safety). O sufixo da função determina obrigatoriamente o tipo de dado que será retornado.

Código
pacman::p_load(purrr)

notas <- list(
  joao = c(10, 9, 8),
  maria = c(5, 6, 7),
  pedro = c(2, 4, 3)
)
  • map(x, fun): Equivalente ao lapply. Retorna sempre uma Lista.
Código
# Retorna uma lista com a média de cada aluno
map(notas, mean)
$joao
[1] 9

$maria
[1] 6

$pedro
[1] 3
  • map_dbl(x, fun): Aplica a função e retorna um vetor Numérico (double).
Código
# Retorna um vetor numérico limpo com as médias
map_dbl(notas, mean)
 joao maria pedro 
    9     6     3 
Dica

Se a função tentar retornar um texto ou booleano, o map_dbl gera um erro imediato, alertando sobre a inconsistência nos dados.

  • map_dfr(x, fun): Aplica a função e tenta empilhar os resultados, retornando um Data Frame unido pelas linhas (Data Frame Row-bind).
Código
# A função anônima (~) cria uma tabela para cada aluno
map_dfr(notas, ~data.frame(
  media = mean(.x), 
  status = if(mean(.x) >= 7) "Aprovado" else "Reprovado"
), .id = "aluno")%>% # .id cria a coluna com o nome da lista original
gt()
aluno media status
joao 9 Aprovado
maria 6 Reprovado
pedro 3 Reprovado
Nota

Se tentássemos usar map_dbl em uma coluna de texto, o R daria erro, protegendo nossa análise de cálculos inválidos.

2.3 Relatórios Dinâmicos (R Markdown e Quarto)

A reprodutibilidade é o pilar da ciência moderna. Ferramentas como R Markdown (.Rmd) e seu sucessor Quarto (.qmd) permitem integrar código, narrativa e resultados em um único documento. Leia os materiais colocados nas referências bibliográficas.

2.4 Tabelas Profissionais

A apresentação de tabelas deve ser adequada ao formato final do relatório (HTML, Word ou PDF).

A. Para Word e PowerPoint (flextable)

Se o seu destino é um documento Office editável, esta é a melhor opção. Converte data frames em objetos nativos do Word.

Código
pacman::p_load(gdtools,flextable)
Tab <- head(mtcars) |> 
  flextable() |> 
  autofit() |> # Ajusta largura das colunas
  color(i = 1, color = "black", part = "header") |> # Cabeçalho vermelho
  save_as_docx(path = "tabela.docx") #salva em word
#
head(mtcars) |> 
  flextable() |> 
  autofit() |> # Ajusta largura das colunas
  color(i = 1, color = "black", part = "header")

B. Para Publicação Acadêmica - HTML/PDF (gt)

Conhecido como o “ggplot das tabelas”. Permite estruturações complexas com notas de rodapé, títulos e agrupamentos.

Código
pacman::p_load(gt)
head(mtcars) |> 
  gt() |> 
  tab_header(title = "") |> 
  fmt_number(columns = c(mpg, wt), decimals = 2) |> # Formatação precisa
  tab_source_note(source_note = "Fonte: Motor Trend")
Análise de Veículos
mpg cyl disp hp drat wt qsec vs am gear carb
21.00 6 160 110 3.90 2.62 16.46 0 1 4 4
21.00 6 160 110 3.90 2.88 17.02 0 1 4 4
22.80 4 108 93 3.85 2.32 18.61 1 1 4 1
21.40 6 258 110 3.08 3.21 19.44 1 0 3 1
18.70 8 360 175 3.15 3.44 17.02 0 0 3 2
18.10 6 225 105 2.76 3.46 20.22 1 0 3 1
Fonte: Motor Trend

C. Para Resumo Estatístico (gtsummary)

Automatiza a criação da Tabela de artigos científicos, calculando descritivas e testes estatísticos automaticamente.

Código
pacman::p_load(gtsummary)
mtcars |> 
  select(mpg, cyl, hp) |> 
  tbl_summary(
    by = cyl, # Agrupa por cilindros
    statistic = list(all_continuous() ~ "{mean} ({sd})")
  ) |> 
  add_p() # Adiciona p-valor (ANOVA/Kruskal)
Characteristic 4
N = 111
6
N = 71
8
N = 141
p-value2
mpg 26.7 (4.5) 19.7 (1.5) 15.1 (2.6) <0.001
hp 83 (21) 122 (24) 209 (51) <0.001
1 Mean (SD)
2 Kruskal-Wallis rank sum test

D. Para Dashboards Interativos (reactable)

Ideal para relatórios HTML onde o usuário precisa filtrar, buscar ou ordenar os dados.

Código
pacman::p_load(reactable)
reactable(
  mtcars,
  searchable = TRUE,  # Adiciona barra de busca
  striped = TRUE,     # Linhas zebradas
  highlight = TRUE    # Destaque ao passar o mouse
)

2.5 Equações Matemáticas (LaTeX)

A escrita matemática em relatórios dinâmicos utiliza a sintaxe LaTeX, o padrão global para tipografia científica. O R Markdown/Quarto renderiza esses códigos em fórmulas visuais de alta qualidade tanto em HTML quanto em PDF.

A. Modos de Exibição (Inline vs. Display)

O modo inline ($) insere a fórmula na fluidez do texto, enquanto o modo display ($$) quebra a linha e centraliza a equação para destaque.

O modelo de regressão linear simples é dado por $y = \alpha + \beta x + \epsilon$.

A estimativa dos parâmetros minimiza a Soma dos Quadrados dos Resíduos:
$$S(\alpha, \beta) = \sum_{i=1}^{n} (y_i - \alpha - \beta x_i)^2$$

O modelo de regressão linear simples é dado por \(y = \alpha + \beta x + \epsilon\).

A estimativa dos parâmetros minimiza a Soma dos Quadrados dos Resíduos: \[S(\alpha, \beta) = \sum_{i=1}^{n} (y_i - \alpha - \beta x_i)^2\]

B. Sintaxe Essencial (Símbolos e Estruturas)

Comandos especiais iniciam com barra invertida (\). Use underscore (_) para subscritos, acento circunflexo (^) para expoentes e chaves {} para agrupar termos.

$$\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i$$

$$\sigma = \sqrt{\frac{\sum(x - \mu)^2}{N}}$$

\[\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i\]

\[\sigma = \sqrt{\frac{\sum(x - \mu)^2}{N}}\]

C. Extração Automática de Modelos (equatiomatic)

Assim como o gtsummary automatiza tabelas, o pacote equatiomatic extrai a equação matemática formatada diretamente de um modelo estatístico ajustado no R.

Código
pacman::p_load(equatiomatic)

modelo <- lm(mpg ~ cyl + hp, data = mtcars)

extract_eq(modelo, use_coefs = TRUE, wrap = TRUE)

\[ \begin{aligned} \operatorname{\widehat{mpg}} &= 36.91 - 2.26(\operatorname{cyl}) - 0.02(\operatorname{hp}) \end{aligned} \]

D. Equações com Valores Dinâmicos (Inline R)

Combine a tipografia LaTeX com o poder do R inserindo códigos executáveis diretamente na fórmula via r código. Garante que os números na equação sejam atualizados se os dados mudarem.

Código
media <- mean(mtcars$mpg)
desvio <- sd(mtcars$mpg)
A distribuição segue uma Normal: $X \sim N(\mu = 20.1, \sigma^2 = 6)$.

A distribuição segue uma Normal: \(X \sim N(\mu = 20.1, \sigma^2 = 6)\).

DicaCheatsheets (Guias de Consulta Rápida)

Decorar todos os comandos e funcionalidades dos pacotes no ecossistema R/RStudio é uma tarefa desafiadora. Por isso, a comunidade desenvolve os chamados cheatsheets (ou folhas de consulta): resumos concisos que reúnem informações essenciais, fórmulas e comandos sobre temas específicos. Eles são projetados para facilitar a consulta rápida, economizar tempo e auxiliar na memorização durante o fluxo de trabalho.

Um dos repositórios mais completos, que inclui guias para pacotes de análise espacial (como o sf), pode ser acessado neste link.

Veja também a formatação de tabelas no link