Skip to Content
Course content

60: Building Models with tidymodels

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Why bother with tidymodels when I can just use a basic function like glm() or randomForest()?

I get this a lot. If you're just running one quick model, glm() is perfectly fine. But the moment you start trying different algorithms—maybe moving from a logistic regression to a random forest to a boosted tree—you'll notice that every single R package has its own weird way of handling formulas, predicting new data, and formatting results. It becomes a nightmare to maintain.

That's where parsnip (the heart of tidymodels) comes in. It creates a unified interface. You define the model type and the engine separately. If you decide to swap your engine from "glm" to "stan", you only change one line of code, and the rest of your pipeline stays exactly the same. Here is how that looks in practice:

library(tidymodels)

# Define a logistic regression model
log_spec <- logistic_reg() %>% 
  set_engine("glm") %>% 
  set_mode("classification")

# Now, if I wanted to try a Random Forest instead, 
# I just change the spec, not the whole workflow:
rf_spec <- rand_forest() %>% 
  set_engine("ranger") %>% 
  set_mode("classification")

It keeps your code clean and prevents you from having to relearn the documentation for every single package on CRAN.

How do I handle data preprocessing without creating ten different versions of my dataframe?

In the old days, we'd manually create dummy variables or scale our data, and then we'd accidentally apply those changes to the test set using the training set's mean—which is a huge no-no called data leakage. I prefer using recipes. Think of a recipe as a set of instructions that you "prep" and then "bake."

Let's say we're predicting whether a customer will churn based on their tenure and monthly charges. We need to normalize the numbers and handle the categorical variables.

churn_recipe <- recipe(churn ~ tenure + monthly_charges + contract_type, data = train_data) %>% 
  step_dummy(contract_type) %>% 
  step_normalize(all_numeric_predictors())

# This doesn't actually change the data yet; it just defines the steps.
# We use 'prep' to calculate the means/SDs on the training data only.
prepared_recipe <- prep(churn_recipe)

# Then 'bake' to apply those exact calculations to any dataset.
baked_train <- bake(prepared_recipe, new_data = train_data)
baked_test <- bake(prepared_recipe, new_data = test_data)

Is there a way to bundle the recipe and the model together so I don't have to call them separately?

Yes, and this is honestly the best part of the ecosystem: workflows. A workflow is basically a container that holds your recipe and your model specification. Instead of manually baking your data and then passing it into a model, you just tell the workflow to "fit" the whole thing.

It makes your code much more readable and significantly reduces the chance of you making a mistake during the deployment phase. I almost always use workflows for anything beyond a toy project.

# Bundle everything together
churn_wf <- workflow() %>% 
  add_recipe(churn_recipe) %>% 
  add_model(log_spec)

# Fit the entire pipeline in one go
final_fit <- fit(churn_wf, data = train_data)

# Now predicting is a breeze
predictions <- predict(final_fit, new_data = test_data)

By wrapping everything in a workflow, tidymodels handles the "prep" and "bake" steps under the hood. You just feed it the raw training data, and it handles the rest.




📋 Practical Task

Build a Wine Quality Classification Workflow

Using the wine dataset (you can use read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=";")), build a tidymodels pipeline to predict if a wine is "high quality" (binary classification).

  • Step 1: Create a binary target variable quality_bin where wines with a quality score of 7 or higher are "high" and others are "low".
  • Step 2: Define a logistic_reg() model specification using the "glm" engine.
  • Step 3: Create a recipe that normalizes all numeric predictors.
  • Step 4: Combine the model and recipe into a workflow.
  • Step 5: Fit the workflow to the data and use predict() to determine the quality category for the first 5 rows of the dataset.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.