Lesson 1 of 6

Reproducible pipelines with targets

You can build a model. Now you have to ship it, and keep it trustworthy. Meet Dev, a data scientist at a meal-kit company. He has one script, analysis.R, that predicts which customers will cancel: it reads the raw orders, aggregates them into per-customer numbers, fits a model, and writes a summary table. Start to finish it takes about 40 minutes, because fitting the model is slow.

This afternoon Dev changed the summary table six times, each time to round a number differently. Six times he waited 40 minutes. This lesson is about the tool that ends that: targets, which reruns only the steps that actually changed.

By the end of this lesson you will be able to:

  • Explain why one long analysis script is slow to iterate on and lets your results quietly drift out of sync with your code
  • Describe a targets pipeline as steps wired into a dependency graph, where each step is the output of a function
  • Predict exactly which steps rerun after a change, so a one-character edit costs seconds instead of 40 minutes

Prerequisites: you can fit a model end to end, you can write a function, and it helps to have met reproducibility with renv and git. The four boxes below are Dev's whole analysis.

The problem

One script reruns everything

Dev's analysis lives in a single file. To run it, he calls source("analysis.R"), and it executes top to bottom:

# analysis.R - the whole analysis in one file
library(readr); library(dplyr)

orders   <- read_csv("orders.csv")   # 12,000 raw order rows
features <- get_features(orders)     # aggregate to 800 customers
model    <- fit_model(features)      # trains the model ... ~38 minutes
summary  <- summarize_model(model)   # the little table at the end
write_csv(summary, "summary.csv")

The trouble is that source() is all-or-nothing. Change the last line, the one that rounds a number in the summary, and R still reruns the 38-minute model fit above it, because it has no idea the model did not change. Every tiny edit costs the full 40 minutes.

So Dev does what everyone does under time pressure: he comments out the slow line and reuses the model object still sitting in his workspace from the last run. It is faster, but now something dangerous has happened. The summary.csv he ships was built from an old model, while the code on disk describes a new one. The results and the code have silently drifted apart, and nobody can tell.

Warning
This is the real cost of the one-big-script habit. Not just slow reruns, but the temptation to skip steps by hand, which lets the output you deliver stop matching the code that supposedly produced it. Reproducibility quietly dies here.