Workflows: Combining Recipes and Models
Bundle preprocessing and model into a single workflow object.
Workflows: Combining Recipes and Models is a free R Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is a Workflow?
A workflow bundles a recipe and a model spec into a single object. This solves a critical problem: preprocessing and modelling steps must be treated as one unit during cross-validation and final fitting, otherwise parameters like normalization means can leak from test folds.
library(workflows)
# Start an empty workflow
wf <- workflow()
print(wf)
# Workflows have two slots: preprocessor and model
# Both must be filled before fittingadd_recipe() and add_model()
Use add_recipe(rec) to attach a recipe preprocessor and add_model(spec) to attach a parsnip model specification. The pipe operator makes this highly readable.
library(recipes)
library(parsnip)
library(workflows)
rec <- recipe(price ~ ., data = train) |>
step_impute_median(all_numeric_predictors()) |>
step_dummy(all_nominal_predictors()) |>
step_normalize(all_numeric_predictors())
spec <- linear_reg() |> set_engine('lm')
wf <- workflow() |>
add_recipe(rec) |>
add_model(spec)
print(wf)fit() on a Workflow
Calling fit(wf, data = train) on a workflow automatically calls prep() on the recipe using the training data and then trains the model on the preprocessed features. You never need to manually call prep() or bake().
fitted_wf <- fit(wf, data = housing_train)
# The fitted workflow stores both the prepped recipe
# and the trained model
print(fitted_wf)predict() on a Fitted Workflow
When you call predict(fitted_wf, new_data = test), the workflow automatically applies bake() to the new data using the trained recipe before generating predictions. This eliminates the risk of forgetting to preprocess test data.
# Predictions automatically preprocess the test data
preds <- predict(fitted_wf, new_data = housing_test)
head(preds)
# For classification
preds_prob <- predict(fitted_wf, new_data = test_df, type = 'prob')
preds_class <- predict(fitted_wf, new_data = test_df, type = 'class')last_fit() — Train on All, Evaluate on Test
last_fit(wf, split) takes your final workflow and the initial train/test split object. It fits the workflow on the training portion and evaluates it on the test portion — the standard final-model evaluation step after tuning is complete.
library(rsample)
split <- initial_split(housing_data, prop = 0.8, strata = price)
# Fit on training, evaluate on test
final_res <- last_fit(wf, split)
# View performance on the held-out test set
collect_metrics(final_res)extract_fit_parsnip()
extract_fit_parsnip(fitted_wf) pulls out the trained parsnip model object from a fitted workflow. You can then use it to inspect coefficients, variable importance, or pass to model-explanation tools.
fitted_wf <- fit(wf, data = housing_train)
# Extract the parsnip model
parsnip_fit <- extract_fit_parsnip(fitted_wf)
# Now access the underlying model
tidy(parsnip_fit) # coefficients for lm
vip::vip(parsnip_fit) # variable importance plotextract_recipe()
extract_recipe(fitted_wf) returns the prepped recipe from a fitted workflow. This is useful for inspecting what transformations were applied or for retrieving the trained preprocessing to apply to external data independently.
fitted_wf <- fit(wf, data = housing_train)
# Get the prepped recipe
prepped_rec <- extract_recipe(fitted_wf)
# Inspect normalization stats
tidy(prepped_rec, number = 3) # step_normalize details
# Apply recipe to completely new external data
new_baked <- bake(prepped_rec, new_data = brand_new_df)augment() on Workflows
augment(fitted_wf, new_data) returns the input data frame with prediction columns appended. For regression it adds .pred; for classification it adds .pred_class and probability columns for each class.
fitted_wf <- fit(wf, data = housing_train)
# Append predictions to the test data frame
results <- augment(fitted_wf, new_data = housing_test)
# Now compute metrics directly
library(yardstick)
results |>
metrics(truth = price, estimate = .pred)Updating a Workflow
You can update individual components of a workflow with update_recipe() or update_model() without rebuilding from scratch. This is handy during experimentation when you want to swap the model engine while keeping the same recipe.
# Original workflow with lm
wf_lm <- workflow() |>
add_recipe(rec) |>
add_model(linear_reg() |> set_engine('lm'))
# Swap model to random forest, keep same recipe
wf_rf <- update_model(
wf_lm,
rand_forest(trees = 300) |>
set_engine('ranger') |>
set_mode('regression')
)
fit_rf <- fit(wf_rf, data = housing_train)add_formula() vs add_recipe()
If you don't need a recipe, you can use add_formula(outcome ~ .) as the preprocessor. This applies minimal transformations (just the formula specification). Use add_recipe() when you need feature engineering; use add_formula() for quick baseline models.
# Simple baseline — no recipe needed
baseline_wf <- workflow() |>
add_formula(price ~ sqft + bedrooms + bathrooms) |>
add_model(linear_reg() |> set_engine('lm'))
baseline_fit <- fit(baseline_wf, data = housing_train)
baseline_preds <- predict(baseline_fit, new_data = housing_test)
# Compare RMSE to recipe-based model
yardstick::rmse_vec(housing_test$price, baseline_preds$.pred)Workflow Sets for Comparison
workflow_set() from the workflowsets package creates a collection of workflows combining multiple recipes and model specs. You can then tune and evaluate all combinations at once with workflow_map().
library(workflowsets)
all_workflows <- workflow_set(
preproc = list(basic = basic_rec, full = full_rec),
models = list(
lm = linear_reg() |> set_engine('lm'),
rf = rand_forest(trees = 200) |> set_engine('ranger') |> set_mode('regression')
)
)
# Fit all 4 combinations on resamples
results <- workflow_map(all_workflows, 'fit_resamples', resamples = cv_folds)
autoplot(results)Quick Check
What is the main advantage of using last_fit(workflow, split) instead of manually fitting and predicting?
Workflows Recap
Key takeaways from Workflows: Combining Recipes and Models:
workflow() |> add_recipe(rec) |> add_model(spec)bundles preprocessing and modelling.fit(wf, data = train)preps the recipe and trains the model in one call.predict(fitted_wf, new_data)automatically bakes new data before predicting.last_fit(wf, split)trains on train, evaluates on test — use for final model assessment.extract_fit_parsnip()andextract_recipe()retrieve components for inspection.augment()appends predictions to the data frame for easy metric calculation.workflow_set()compares multiple recipe-model combinations simultaneously.
# Canonical tidymodels workflow pattern
split <- initial_split(data, prop = 0.8)
train <- training(split)
test <- testing(split)
rec <- recipe(y ~ ., data = train) |> step_normalize(all_numeric_predictors())
spec <- rand_forest(trees = 300) |> set_engine('ranger') |> set_mode('regression')
wf <- workflow() |> add_recipe(rec) |> add_model(spec)
final_res <- last_fit(wf, split)
collect_metrics(final_res)Frequently asked questions
Is the “Workflows: Combining Recipes and Models” lesson free?
Yes — the full text of “Workflows: Combining Recipes and Models” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.
What will I learn in “Workflows: Combining Recipes and Models”?
Bundle preprocessing and model into a single workflow object. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start R Academy?
No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Workflows: Combining Recipes and Models” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this R Academy lesson?
Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Feature Engineering with recipes
- Model Specifications with parsnip
- Workflows: Combining Recipes and Models
- Resampling and Cross-Validation with rsample