This analysis examines how marketing analytics can be used to better understand consumer preferences and identify meaningful customer segments. Part 1 discusses the Dairy Foods yogurt beverage consumer-insight case and the marketing analytics methods used to understand consumer preferences. Part 2 applies K-means cluster analysis to customer survey data to identify groups of consumers with similar attitudes and behaviors.
The Dairy Foods case, “Consumer Insight on Yogurt Beverages,” demonstrates how consumer research can help companies better understand what customers want from a product. Rather than assuming that all consumers have the same preferences, the research examines differences among consumers and identifies groups that respond differently to product characteristics and marketing messages.
This type of analysis is valuable because companies can use consumer data to make better decisions about product development, positioning, promotion, and target markets.
The consulting research described in the case used quantitative consumer research to evaluate preferences for yogurt beverages. One important marketing analytics technique discussed in the case is conjoint analysis. Conjoint analysis allows researchers to evaluate how consumers respond to different combinations of product characteristics.
The research also demonstrates the importance of market segmentation. Instead of viewing all consumers as one group, researchers identified different types of consumers based on their preferences and responses.
The case identified consumer groups such as variety seekers, traditionalists, and impressionable consumers. These groups demonstrated that different customers can respond differently to flavors, descriptions, product characteristics, and marketing messages.
The main lesson from the results is that there is not necessarily one yogurt beverage that will appeal equally to every consumer. Different groups of consumers value different characteristics.
For marketers, this means that a company may be more successful when it identifies specific customer segments and develops products and promotional strategies for those groups. For example, consumers who enjoy variety may respond to new flavors and product options, while more traditional consumers may prefer simple and familiar products.
The findings demonstrate why segmentation is important in marketing analytics. Averages alone can hide meaningful differences between groups of customers.
This case provides a useful framework for our group project because it demonstrates how customer data can be transformed into actionable marketing recommendations. Instead of only calculating overall averages from survey responses, our group can identify groups of customers who have similar attitudes and behaviors.
Cluster analysis can help us identify these customer segments. Once the clusters have been identified, we can examine the characteristics of each group and recommend different marketing strategies for each segment.
The case therefore demonstrates the connection between collecting customer data, analyzing that data, identifying consumer segments, and making marketing recommendations.
The case demonstrates several responsibilities that marketing analysts may have in their careers. Marketing analysts collect and analyze customer data, identify consumer preferences, evaluate market segments, and communicate their findings to managers.
Marketing analytics professionals may use techniques such as surveys, customer segmentation, conjoint analysis, cluster analysis, and data visualization. However, the analyst’s job is not only to calculate statistics. Analysts must also translate statistical findings into recommendations that help organizations make better marketing decisions.
The purpose of this analysis is to identify groups of customers with similar attitudes and behaviors. K-means cluster analysis will be used to divide survey respondents into customer segments.
Demographic variables such as ID, gender, age, and education are not used to create the clusters. Instead, behavioral and attitudinal survey variables are used to form the segments. Demographic information is examined afterward to help describe the resulting customer groups.
# ============================================================
# 1. IMPORT THE DATA
# ============================================================
data <- read.csv(
"customer_segmentation.csv",
check.names = FALSE
)
# Remove accidental spaces from column names
names(data) <- trimws(names(data))
cat("VARIABLES IN DATASET:\n")
## VARIABLES IN DATASET:
print(names(data))
## [1] "ID" "CS_helpful" "Recommend" "Come_again"
## [5] "All_Products" "Profesionalism" "Limitation" "Online_grocery"
## [9] "delivery" "Pick_up" "Find_items" "other_shops"
## [13] "Gender" "Age" "Education"
cat("\nNUMBER OF RESPONDENTS:\n")
##
## NUMBER OF RESPONDENTS:
print(nrow(data))
## [1] 22
cat("\nDATA STRUCTURE:\n")
##
## DATA STRUCTURE:
str(data)
## 'data.frame': 22 obs. of 15 variables:
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ CS_helpful : int 2 1 2 3 2 1 2 1 1 1 ...
## $ Recommend : int 2 2 1 3 1 1 1 1 1 1 ...
## $ Come_again : int 2 1 1 2 3 3 1 1 1 1 ...
## $ All_Products : int 2 1 1 4 5 2 2 2 2 1 ...
## $ Profesionalism: int 2 1 1 1 2 1 2 1 2 1 ...
## $ Limitation : int 2 1 2 2 1 1 1 2 1 1 ...
## $ Online_grocery: int 2 2 3 3 2 1 2 1 2 3 ...
## $ delivery : int 3 3 3 3 3 2 2 1 1 2 ...
## $ Pick_up : int 4 3 2 2 1 1 2 2 3 2 ...
## $ Find_items : int 1 1 1 2 2 1 1 2 1 1 ...
## $ other_shops : int 2 2 3 2 3 4 1 4 1 1 ...
## $ Gender : int 1 1 1 1 2 1 1 1 2 2 ...
## $ Age : int 2 2 2 3 4 2 2 2 2 2 ...
## $ Education : int 2 2 2 5 2 5 3 2 1 2 ...
Before performing cluster analysis, the dataset is checked for missing values.
# ============================================================
# 2. CHECK MISSING VALUES
# ============================================================
missing_values <- colSums(is.na(data))
print(missing_values)
## ID CS_helpful Recommend Come_again All_Products
## 0 0 0 0 0
## Profesionalism Limitation Online_grocery delivery Pick_up
## 0 0 0 0 0
## Find_items other_shops Gender Age Education
## 0 0 0 0 0
The following variables measure customer attitudes, shopping behavior, and preferences and will therefore be used to create the customer segments.
# ============================================================
# 3. SELECT CLUSTERING VARIABLES
# ============================================================
cluster_data <- data[, c(
"CS_helpful",
"Recommend",
"Come_again",
"All_Products",
"Profesionalism",
"Limitation",
"Online_grocery",
"delivery",
"Pick_up",
"Find_items",
"other_shops"
)]
cat("VARIABLES USED FOR CLUSTERING:\n")
## VARIABLES USED FOR CLUSTERING:
print(names(cluster_data))
## [1] "CS_helpful" "Recommend" "Come_again" "All_Products"
## [5] "Profesionalism" "Limitation" "Online_grocery" "delivery"
## [9] "Pick_up" "Find_items" "other_shops"
cat("\nSUMMARY OF VARIABLES:\n")
##
## SUMMARY OF VARIABLES:
print(summary(cluster_data))
## CS_helpful Recommend Come_again All_Products
## Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
## 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:1.250
## Median :1.000 Median :1.000 Median :1.000 Median :2.000
## Mean :1.591 Mean :1.318 Mean :1.455 Mean :2.091
## 3rd Qu.:2.000 3rd Qu.:1.000 3rd Qu.:2.000 3rd Qu.:2.000
## Max. :3.000 Max. :3.000 Max. :3.000 Max. :5.000
## Profesionalism Limitation Online_grocery delivery Pick_up
## Min. :1.000 Min. :1.0 Min. :1.000 Min. :1.000 Min. :1.000
## 1st Qu.:1.000 1st Qu.:1.0 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000
## Median :1.000 Median :1.0 Median :2.000 Median :3.000 Median :2.000
## Mean :1.409 Mean :1.5 Mean :2.273 Mean :2.409 Mean :2.455
## 3rd Qu.:2.000 3rd Qu.:2.0 3rd Qu.:3.000 3rd Qu.:3.000 3rd Qu.:3.000
## Max. :3.000 Max. :4.0 Max. :3.000 Max. :3.000 Max. :5.000
## Find_items other_shops
## Min. :1.000 Min. :1.000
## 1st Qu.:1.000 1st Qu.:1.250
## Median :1.000 Median :2.000
## Mean :1.455 Mean :2.591
## 3rd Qu.:2.000 3rd Qu.:3.750
## Max. :3.000 Max. :5.000
Any respondent with missing information on the clustering variables is removed before the analysis.
# ============================================================
# 4. REMOVE INCOMPLETE OBSERVATIONS
# ============================================================
complete_rows <- complete.cases(cluster_data)
cluster_clean <- cluster_data[complete_rows, ]
data_clean <- data[complete_rows, ]
cat(
"Number of observations included in cluster analysis:",
nrow(cluster_clean),
"\n"
)
## Number of observations included in cluster analysis: 22
The variables are standardized before running K-means clustering. Standardization places the variables on a comparable scale and prevents variables with larger numerical ranges from having an unfair influence on the clustering results.
# ============================================================
# 5. STANDARDIZE DATA
# ============================================================
scaled_data <- scale(cluster_clean)
cat("First few standardized observations:\n")
## First few standardized observations:
print(head(scaled_data))
## CS_helpful Recommend Come_again All_Products Profesionalism Limitation
## 1 0.5572385 1.0548991 0.7385489 -0.08536162 1.0009877 0.6236096
## 2 -0.8049001 1.0548991 -0.6154575 -1.02433946 -0.6929915 -0.6236096
## 3 0.5572385 -0.4922862 -0.6154575 -1.02433946 -0.6929915 0.6236096
## 4 1.9193772 2.6020844 0.7385489 1.79259406 -0.6929915 0.6236096
## 5 0.5572385 -0.4922862 2.0925553 2.73157191 1.0009877 -0.6236096
## 6 -0.8049001 -0.4922862 2.0925553 -0.08536162 -0.6929915 -0.6236096
## Online_grocery delivery Pick_up Find_items other_shops
## 1 -0.3554390 0.8049001 1.4623535 -0.6774335 -0.4212692
## 2 -0.3554390 0.8049001 0.5161248 -0.6774335 -0.4212692
## 3 0.9478374 0.8049001 -0.4301040 -0.6774335 0.2916479
## 4 0.9478374 0.8049001 -0.4301040 0.8129201 -0.4212692
## 5 -0.3554390 0.8049001 -1.3763327 0.8129201 0.2916479
## 6 -1.6587154 -0.5572385 -1.3763327 -0.6774335 1.0045650
The elbow method compares the within-cluster sum of squares for different numbers of clusters. An appropriate number of clusters is generally located where the improvement begins to level off.
# ============================================================
# 6. ELBOW METHOD
# ============================================================
set.seed(123)
wss <- numeric(6)
for (k in 1:6) {
elbow_model <- kmeans(
scaled_data,
centers = k,
nstart = 25
)
wss[k] <- elbow_model$tot.withinss
}
plot(
1:6,
wss,
type = "b",
pch = 19,
xlab = "Number of Clusters",
ylab = "Within-Cluster Sum of Squares",
main = "Elbow Method"
)
The elbow graph allows us to compare solutions containing different numbers of customer segments. For this exploratory analysis, a three-cluster solution is used because it provides customer groups that can be compared and interpreted from a marketing perspective.
# ============================================================
# 7. K-MEANS CLUSTER ANALYSIS
# ============================================================
set.seed(123)
k3 <- kmeans(
scaled_data,
centers = 3,
nstart = 25
)
cat("K-MEANS RESULTS:\n")
## K-MEANS RESULTS:
print(k3)
## K-means clustering with 3 clusters of sizes 4, 10, 8
##
## Cluster means:
## CS_helpful Recommend Come_again All_Products Profesionalism Limitation
## 1 1.2383079 1.05489907 1.4155521 1.08836068 1.00098765 0.6236096
## 2 -0.6686862 -0.49228623 -0.2092555 -0.08536162 -0.35419563 -0.4988877
## 3 0.2167039 0.08790826 -0.4462067 -0.43747831 -0.05774929 0.3118048
## Online_grocery delivery Pick_up Find_items other_shops
## 1 -0.02961992 0.8049001 -1.1397755 0.81292014 0.1134186
## 2 -0.35543902 -0.9658801 -0.2408582 -0.37936273 0.1490645
## 3 0.45910874 0.8049001 0.8709605 0.06774335 -0.2430399
##
## Clustering vector:
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
## 3 3 3 1 1 2 2 2 2 2 2 2 2 3 2 2 3 3 1 1 3 3
##
## Within cluster sum of squares by cluster:
## [1] 47.23351 54.34381 48.23893
## (between_SS / total_SS = 35.1 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
# ============================================================
# 8. CLUSTER SIZES
# ============================================================
cat("NUMBER OF CUSTOMERS IN EACH CLUSTER:\n")
## NUMBER OF CUSTOMERS IN EACH CLUSTER:
print(k3$size)
## [1] 4 10 8
cat("\nCLUSTER FREQUENCY TABLE:\n")
##
## CLUSTER FREQUENCY TABLE:
print(table(k3$cluster))
##
## 1 2 3
## 4 10 8
# ============================================================
# 9. ADD CLUSTERS TO DATASET
# ============================================================
data_clean$Cluster <- factor(k3$cluster)
cat("FIRST CUSTOMERS WITH CLUSTER ASSIGNMENTS:\n")
## FIRST CUSTOMERS WITH CLUSTER ASSIGNMENTS:
print(
head(
data_clean[, c("ID", "Cluster")]
)
)
## ID Cluster
## 1 1 3
## 2 2 3
## 3 3 3
## 4 4 1
## 5 5 1
## 6 6 2
Principal component analysis is used only to display the multidimensional cluster results on a two-dimensional graph.
# ============================================================
# 10. PRINCIPAL COMPONENT ANALYSIS
# ============================================================
pca_result <- prcomp(
scaled_data,
center = FALSE,
scale. = FALSE
)
plot(
pca_result$x[, 1],
pca_result$x[, 2],
col = k3$cluster,
pch = 19,
cex = 1.5,
main = "Customer Segmentation Using K-Means",
xlab = "Principal Component 1",
ylab = "Principal Component 2"
)
legend(
"topright",
legend = c(
"Cluster 1",
"Cluster 2",
"Cluster 3"
),
col = c(1, 2, 3),
pch = 19
)
Customers located closer together on the graph have more similar response patterns across the survey variables. Customers that appear farther apart have more different response patterns. The three cluster labels identify the customer segments created by the K-means analysis.
The next step calculates the average response for each survey variable within each cluster. These averages are important because they allow us to understand what makes each customer segment different.
# ============================================================
# 11. CREATE CLUSTER PROFILES
# ============================================================
profile_data <- cluster_clean
profile_data$Cluster <- factor(k3$cluster)
cluster_profiles <- aggregate(
profile_data[, 1:11],
by = list(
Cluster = profile_data$Cluster
),
FUN = mean
)
# Round numbers
cluster_profiles_rounded <- cluster_profiles
cluster_profiles_rounded[, -1] <- round(
cluster_profiles_rounded[, -1],
2
)
cat("AVERAGE SCORES FOR EACH CUSTOMER SEGMENT:\n")
## AVERAGE SCORES FOR EACH CUSTOMER SEGMENT:
print(cluster_profiles_rounded)
## Cluster CS_helpful Recommend Come_again All_Products Profesionalism
## 1 1 2.50 2.00 2.50 3.25 2.00
## 2 2 1.10 1.00 1.30 2.00 1.20
## 3 3 1.75 1.38 1.12 1.62 1.38
## Limitation Online_grocery delivery Pick_up Find_items other_shops
## 1 2.00 2.25 3.0 1.25 2.0 2.75
## 2 1.10 2.00 1.7 2.20 1.2 2.80
## 3 1.75 2.62 3.0 3.38 1.5 2.25
barplot(
cluster_profiles$CS_helpful,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Customer Service Helpfulness",
xlab = "Customer Segment",
ylab = "Average Score"
)
barplot(
cluster_profiles$Recommend,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Likelihood to Recommend",
xlab = "Customer Segment",
ylab = "Average Score"
)
barplot(
cluster_profiles$Come_again,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Intention to Return",
xlab = "Customer Segment",
ylab = "Average Score"
)
barplot(
cluster_profiles$Online_grocery,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Online Grocery Preference",
xlab = "Customer Segment",
ylab = "Average Score"
)
barplot(
cluster_profiles$delivery,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Delivery Preference",
xlab = "Customer Segment",
ylab = "Average Score"
)
barplot(
cluster_profiles$Pick_up,
names.arg = paste(
"Cluster",
cluster_profiles$Cluster
),
main = "Pickup Preference",
xlab = "Customer Segment",
ylab = "Average Score"
)
Demographic variables were not used to create the clusters. However, they can be compared after clustering to better understand who belongs to each segment.
cat("GENDER BY CLUSTER:\n")
## GENDER BY CLUSTER:
gender_clusters <- table(
Cluster = data_clean$Cluster,
Gender = data_clean$Gender
)
print(gender_clusters)
## Gender
## Cluster 1 2
## 1 1 3
## 2 7 3
## 3 8 0
cat("AGE BY CLUSTER:\n")
## AGE BY CLUSTER:
age_clusters <- table(
Cluster = data_clean$Cluster,
Age = data_clean$Age
)
print(age_clusters)
## Age
## Cluster 2 3 4
## 1 2 1 1
## 2 6 2 2
## 3 7 1 0
cat("EDUCATION BY CLUSTER:\n")
## EDUCATION BY CLUSTER:
education_clusters <- table(
Cluster = data_clean$Cluster,
Education = data_clean$Education
)
print(education_clusters)
## Education
## Cluster 1 2 3 5
## 1 0 2 1 1
## 2 2 2 1 5
## 3 1 4 0 3
The following graph compares all of the average survey responses across the three customer segments.
# ============================================================
# 12. OVERALL CLUSTER PROFILE GRAPH
# ============================================================
profile_matrix <- as.matrix(
cluster_profiles[, -1]
)
profile_matrix <- t(profile_matrix)
matplot(
profile_matrix,
type = "b",
pch = c(19, 17, 15),
lty = 1,
xaxt = "n",
xlab = "",
ylab = "Average Survey Response",
main = "Customer Segment Profiles"
)
axis(
1,
at = 1:nrow(profile_matrix),
labels = rownames(profile_matrix),
las = 2,
cex.axis = 0.65
)
legend(
"topright",
legend = c(
"Cluster 1",
"Cluster 2",
"Cluster 3"
),
pch = c(19, 17, 15),
lty = 1
)
The following code saves a copy of the original customer data with each respondent’s cluster assignment. It also creates a second file containing the average profile for each cluster.
# ============================================================
# 13. EXPORT RESULTS
# ============================================================
write.csv(
data_clean,
"Customer_Segmentation_Results.csv",
row.names = FALSE
)
write.csv(
cluster_profiles_rounded,
"Cluster_Profiles.csv",
row.names = FALSE
)
cat("RESULT FILES CREATED SUCCESSFULLY.\n")
## RESULT FILES CREATED SUCCESSFULLY.
# ============================================================
# 14. FINAL SUMMARY
# ============================================================
cat("==============================================\n")
## ==============================================
cat("CUSTOMER SEGMENTATION ANALYSIS RESULTS\n")
## CUSTOMER SEGMENTATION ANALYSIS RESULTS
cat("==============================================\n")
## ==============================================
cat(
"\nNumber of respondents analyzed:",
nrow(data_clean),
"\n"
)
##
## Number of respondents analyzed: 22
cat("\nNumber of respondents in each cluster:\n")
##
## Number of respondents in each cluster:
print(
table(data_clean$Cluster)
)
##
## 1 2 3
## 4 10 8
cat("\nAverage customer segment profiles:\n")
##
## Average customer segment profiles:
print(cluster_profiles_rounded)
## Cluster CS_helpful Recommend Come_again All_Products Profesionalism
## 1 1 2.50 2.00 2.50 3.25 2.00
## 2 2 1.10 1.00 1.30 2.00 1.20
## 3 3 1.75 1.38 1.12 1.62 1.38
## Limitation Online_grocery delivery Pick_up Find_items other_shops
## 1 2.00 2.25 3.0 1.25 2.0 2.75
## 2 1.10 2.00 1.7 2.20 1.2 2.80
## 3 1.75 2.62 3.0 3.38 1.5 2.25
cat("\nAnalysis completed successfully.\n")
##
## Analysis completed successfully.
The K-means cluster analysis separates respondents into three groups based on similarities in their customer attitudes and shopping preferences. The cluster profile table above should be used to determine which variables are particularly high or low for each segment.
A cluster with relatively high scores for recommendation, intention to return, and customer-service helpfulness may represent more satisfied and loyal customers. A segment with stronger online grocery, delivery, or pickup scores may represent convenience-oriented or digitally oriented shoppers. A group with lower satisfaction or loyalty scores may represent customers who require additional attention and could potentially be targeted with service improvements or retention strategies.
These differences are useful to marketers because the company does not need to use the same strategy for every customer. Instead, promotions, communication, service improvements, and digital shopping options can be designed around the needs of individual customer segments.
The yogurt beverage case and the customer segmentation analysis demonstrate the same important marketing concept: consumers are heterogeneous. Different customers have different preferences, motivations, and behaviors.
The yogurt beverage case demonstrates how consumer research can reveal different types of consumers based on their responses to product characteristics and marketing messages. Similarly, the K-means analysis uses survey responses to identify groups of customers with similar characteristics.
Both analyses demonstrate how marketing analytics can move beyond overall averages and help companies identify meaningful customer segments.
This exercise demonstrates several skills that are useful in marketing analytics careers. Marketing analysts must be able to clean customer data, select appropriate variables, perform statistical analysis, visualize results, and interpret the business meaning of their findings.
Cluster analysis is particularly useful for customer segmentation because it can help companies identify target markets and develop differentiated marketing strategies. These skills can be applied in careers involving market research, consumer insights, digital marketing, customer analytics, business intelligence, and marketing strategy.
One important limitation of this analysis is the relatively small survey sample. Because the dataset contains a limited number of respondents, the clusters should be interpreted as exploratory customer segments rather than definitive representations of the larger customer population.
A larger sample would provide greater confidence that the customer segments identified in the analysis represent meaningful patterns in the overall target market.
The case analysis and cluster analysis demonstrate how marketing analytics can transform consumer data into useful business insights. The yogurt beverage case shows how companies can identify differences in consumer preferences, while the K-means analysis demonstrates how survey respondents can be divided into meaningful customer segments.
Together, these approaches show that marketing analytics is not simply about calculating statistics. The ultimate goal is to use data to better understand customers and make informed decisions about targeting, positioning, customer experience, and marketing strategy.