Skip to Content
Course content

218: Capstone: Building a Customer Segmentation and Targeting System

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

Imagine you're organizing a massive wedding. You have a guest list of 500 people. You can't possibly write a unique, heartfelt note to every single person, but you also can't send the exact same generic "thanks for coming" card to your grandmother, your old college roommate, and your boss. Instead, you group them. You've got the "Inner Circle," the "Extended Family," and the "Professional Contacts." Once they're grouped, you can tailor your message—and your budget—to each group specifically.

Building a customer segmentation system in R works exactly like that. We aren't just looking at a list of names; we're looking for behavioral patterns. Here is how that analogy maps to the code we're about to write:

  • The Guest List is your raw transaction dataset.
  • The Relationship Criteria (how often you talk, how close you are) are your RFM metrics: Recency, Frequency, and Monetary value.
  • The Grouping Process is the K-means clustering algorithm, which mathematically decides who belongs in which "bucket."
  • The Tailored Message is your targeting strategy—deciding which group gets a discount code and which group gets a loyalty reward.

Turning Raw Transactions into Behavioral Signals

We can't just feed a list of every single purchase into a clustering algorithm; it's too noisy. We need to collapse those transactions into a "customer profile." In the industry, we almost always start with RFM. I've found that while there are fancier models, RFM is the "bread and butter" because it's easy to explain to stakeholders.

library(tidyverse)
library(lubridate)

# Assuming 'df' is our raw transaction data with CustomerID, Date, and Amount
rfm_data <- df %>%
  group_by(CustomerID) %>%
  summarise(
    Recency = as.numeric(as.Date("2023-12-31") - max(Date)),
    Frequency = n(),
    Monetary = sum(Amount)
  ) %>%
  drop_na()

# Clustering is sensitive to scale. If Monetary is in the thousands 
# and Frequency is 1-10, the algorithm will ignore Frequency.
rfm_scaled <- scale(rfm_data[, 2:4])

Hunting for the Sweet Spot with the Elbow Method

The hardest part of K-means is deciding how many clusters (K) to actually use. If you pick too many, you're just overcomplicating things. Too few, and you're grouping "VIPs" with "one-time buyers." I usually rely on the "Elbow Method." We run the model for a range of K values and look for the point where the improvement in "within-cluster sum of squares" starts to flatten out.

library(factoextra)

# We'll check 1 through 10 clusters
fviz_nbclust(rfm_scaled, kmeans, method = "wss") +
  labs(title = "Determining Optimal Clusters", x = "Number of Clusters", y = "Total Within-Cluster Sum of Squares")

When you look at that plot, you're looking for the "bend" in the arm. If the bend happens at K=4, that's your magic number. It means adding a fifth cluster doesn't actually give you much more insight.

Assigning Personas to the Clusters

Once we run the K-means, R gives us cluster numbers (1, 2, 3...), but "Cluster 1" means nothing to a marketing manager. This is where you step in as the analyst to assign a persona based on the cluster means.

# Running the model with 4 clusters
set.seed(123) # Keep it reproducible
km_res <- kmeans(rfm_scaled, centers = 4, nstart = 25)

# Add the cluster assignment back to our original data
rfm_final <- rfm_data %>%
  mutate(Cluster = as.factor(km_res$cluster))

# Now, let's see who these people actually are
cluster_profiles <- rfm_final %>%
  group_by(Cluster) %>%
  summarise(
    Avg_Recency = mean(Recency),
    Avg_Freq = mean(Frequency),
    Avg_Monetary = mean(Monetary)
  )

At this point, I'd look at the cluster_profiles table. If Cluster 2 has low recency (bought recently), high frequency, and high monetary value, I'm labeling them "Champions." If Cluster 4 has high recency (hasn't been seen in months) and low frequency, they're "At-Risk."

Seeing the Segments in Action

Numbers are great, but a visualization is what sells the project. I prefer a 3D scatter plot or a series of 2D plots to ensure the clusters actually look separated. If they're just one giant blob, you might need to revisit your scaling or try a different number of clusters.

fviz_cluster(km_res, data = rfm_scaled, 
              geom = "point", 
              ellipse.type = "convex", 
              ggtheme = theme_minimal(),
              main = "Customer Segment Visualization")



📋 Practical Task

Project: High-Value Customer Identification Pipeline for a Subscription Service

You have been handed a dataset of 1,000 subscribers for a streaming service. The dataset subscription_data.csv contains UserID, LastLoginDate, TotalMoviesWatched, and TotalSpend.

Your task is to build a complete segmentation pipeline. You must:

  1. Feature Engineer: Calculate the Recency (days since last login relative to 2024-01-01), Frequency (TotalMoviesWatched), and Monetary (TotalSpend) for each user.
  2. Pre-process: Scale the data to ensure TotalSpend doesn't dominate the clustering.
  3. Optimize: Use the Elbow Method to justify your choice of K.
  4. Segment: Run the K-means algorithm and create a new column in your final dataframe called UserSegment.
  5. Analyze: Print a summary table showing the average values for each segment and assign a descriptive name to each segment (e.g., "Power Users", "Churn Risks", "Casuals") based on their behavior.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.