R e Python não competem — se complementam. R brilha em estatística, visualização e, com o tidymodels e o mlr3, tem um dos ecossistemas de ML mais elegantes que existem. Esta aula revisa o R que você usará no curso: o tidyverse para manipular dados e o tidymodels para modelar sem vazamento, espelhando os conceitos de pipeline já vistos.

Dominar o fluxo de dados em R com dplyr/tidyr, entender o pipe |>, e construir workflows de ML reprodutíveis com tidymodels (recipes, workflows, resamples).

O pipe e a gramática do tidyverse

O operador pipe encadeia operações da esquerda para a direita, tornando o código legível como uma receita.

library(tidyverse)

dados <- tibble(
  idade        = c(25, 42, 31, 55, 28, 40),
  renda        = c(3200, 8500, 4100, 12000, 3800, 7200),
  regiao       = c("sul", "sul", "norte", "leste", "norte", "leste"),
  inadimplente = c(0, 0, 1, 0, 1, 0)
)

resumo <- dados |>
  filter(idade < 50) |>
  mutate(renda_log = log1p(renda)) |>
  group_by(regiao) |>
  summarise(
    renda_media = mean(renda),
    taxa_inad   = mean(inadimplente),
    n           = n()
  )

print(resumo)

Os cinco verbos centrais do dplyr: filter (linhas), select (colunas), mutate (novas colunas), arrange (ordenar), summarise + group_by (agregar). Com eles você faz 90% da manipulação de dados.

Dados largos e longos com tidyr

library(tidyr)

# Formato largo -> longo (útil para plotar múltiplas métricas)
largo <- tibble(
  modelo = c("rf", "xgb"),
  auc    = c(0.82, 0.86),
  f1     = c(0.71, 0.75)
)

longo <- largo |>
  pivot_longer(cols = c(auc, f1), names_to = "metrica", values_to = "valor")

print(longo)

Visualização com ggplot2

library(ggplot2)

ggplot(dados, aes(x = idade, y = renda, color = factor(inadimplente))) +
  geom_point(size = 3) +
  scale_color_manual(values = c("0" = "steelblue", "1" = "firebrick"),
                     name = "Inadimplente") +
  labs(title = "Renda vs. Idade", x = "Idade", y = "Renda") +
  theme_minimal()

A gramática de gráficos (ggplot2) constrói visualizações por camadas: dados + estética (aes) + geometrias (geom_*) + escalas + temas. É a melhor ferramenta de visualização estatística disponível em qualquer linguagem.

tidymodels — ML sem vazamento em R

O tidymodels separa claramente as etapas: recipe (pré-processamento), model spec (algoritmo), workflow (une os dois), resamples (validação).

library(tidymodels)

dados <- dados |> mutate(inadimplente = factor(inadimplente))

# 1. Split treino/teste
set.seed(42)
split  <- initial_split(dados, prop = 0.7, strata = inadimplente)
treino <- training(split)
teste  <- testing(split)

# 2. Recipe: pré-processamento (aprende parâmetros só no treino)
receita <- recipe(inadimplente ~ ., data = treino) |>
  step_impute_median(all_numeric_predictors()) |>
  step_normalize(all_numeric_predictors()) |>
  step_dummy(all_nominal_predictors())

# 3. Especificação do modelo
modelo_rf <- rand_forest(trees = 200) |>
  set_engine("ranger") |>
  set_mode("classification")

# 4. Workflow: recipe + modelo
wf <- workflow() |>
  add_recipe(receita) |>
  add_model(modelo_rf)

# 5. Validação cruzada
set.seed(42)
folds <- vfold_cv(treino, v = 5, strata = inadimplente)

resultados <- fit_resamples(
  wf, resamples = folds,
  metrics = metric_set(roc_auc, accuracy, f_meas)
)

collect_metrics(resultados)

Repare no paralelo com o Pipeline do sklearn: a recipe dentro do workflow garante que cada fold re-aprenda a imputação, normalização e dummies apenas no treino — mesma defesa contra vazamento, sintaxe diferente.

Ajuste final e avaliação no teste

# Treina no treino completo e avalia no teste — uma única vez
final_fit <- last_fit(wf, split,
                      metrics = metric_set(roc_auc, accuracy, f_meas))

collect_metrics(final_fit)          # métricas no teste
collect_predictions(final_fit)      # predições para análise/curvas

last_fit é a forma correta de reportar o desempenho final: ele treina no treino inteiro e prevê no teste uma só vez, sem contaminação.

mlr3 — a alternativa orientada a objetos

Para quem prefere um framework mais programático e modular:

library(mlr3verse)

task <- as_task_classif(dados, target = "inadimplente")
learner <- lrn("classif.ranger", num.trees = 200, predict_type = "prob")

resampling <- rsmp("cv", folds = 5)
rr <- resample(task, learner, resampling)

rr$aggregate(msr("classif.auc"))

mlr3 é especialmente forte em benchmarking de muitos modelos, tuning aninhado e pipelines complexos (mlr3pipelines) — voltaremos a ele nos Módulos 1 e 5.

O pipe |> e os verbos do dplyr formam uma gramática legível para manipular dados; o tidyr reorganiza entre os formatos largo e longo, e o ggplot2 visualiza por camadas. O tidymodels separa as peças — recipe para o pré-processamento, model spec, workflow e resamples — e é a recipe dentro do workflow que evita vazamento, exatamente como o Pipeline do scikit-learn faz do outro lado. O last_fit reporta o desempenho final no teste uma vez só, que é como deve ser. E o mlr3 é a alternativa orientada a objetos, forte em benchmarking e tuning.

Exercícios

  1. Qual é o equivalente em tidymodels do Pipeline do scikit-learn, e por que ele previne vazamento de dados na validação cruzada?

    ✓ Resposta:

    O workflow combinado com a recipe. A recipe define passos de pré-processamento que aprendem parâmetros (mediana para imputação, média/desvio para normalização, níveis de categorias para dummies). Ao passar o workflow para fit_resamples/vfold_cv, cada fold reajusta a recipe apenas no subconjunto de treino daquele fold, de modo que nenhuma estatística do fold de validação vaza para o pré-processamento — exatamente o papel do Pipeline no sklearn.

  2. Escreva um trecho dplyr que, a partir de dados, retorne a renda média e a taxa de inadimplência por região, ordenadas da maior para a menor taxa.

    ✓ Resposta:
    dados |>
      group_by(regiao) |>
      summarise(renda_media = mean(renda),
                taxa_inad   = mean(as.numeric(as.character(inadimplente)))) |>
      arrange(desc(taxa_inad))

    (Se inadimplente for numérico, dispensa a conversão; se for fator, converta antes de calcular a média.)

  3. Qual a diferença entre fit_resamples e last_fit, e quando usar cada um?

    ✓ Resposta:

    fit_resamples roda validação cruzada (ou outro resampling) para estimar o desempenho e comparar/ajustar modelos — pode ser chamado várias vezes durante a experimentação. last_fit é usado uma única vez ao final: treina no conjunto de treino completo e avalia no conjunto de teste retido, produzindo a estimativa final imparcial. Nunca use o teste repetidamente para tomar decisões — isso reintroduz viés de seleção.

  4. Cite uma vantagem do mlr3 sobre o tidymodels e uma do tidymodels sobre o mlr3.

    ✓ Resposta:

    mlr3 tende a ser mais modular e programático, com excelente suporte a benchmarking em larga escala de muitos learners e a tuning aninhado (mlr3tuning + AutoTuner), integrando-se bem a pipelines complexos. tidymodels costuma ter sintaxe mais legível e "tidyverse-native", curva de aprendizado mais suave e documentação muito acessível. A escolha é em boa parte de estilo; ambos são de ponta.

Fontes e leituras recomendadas