Repository navigation
Expand file tree
/
Copy pathStarbucks_Final.Rmd
More file actions
302 lines (203 loc) · 6.44 KB
/
Copy pathStarbucks_Final.Rmd
File metadata and controls
302 lines (203 loc) · 6.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
---
title: "Data Brew: Brewing Success with Starbucks Customer Insights"
subtitle: "TEAM 6 - Chekitha Swayampu, Hrushikesh Sai Seshagiri Chowdary Uppalapati, Swathi Murali Srinivasan, Vaishnavi Tamilvanan"
date: "2023-10-20"
output:
prettydoc::html_pretty:
theme: hpstr
toc: true
pdf_document:
toc: yes
toc_depth: 3
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
# Load required libraries
library(jsonlite)
library(dplyr)
# Load data
portfolio <- read.csv("data/portfolio.csv", row.names = 1)
profile <- read.csv("data/profile.csv", row.names = 1)
transcript <- read.csv("data/transcript.csv", row.names =1)
```
## DATA CLEANING AND PREPROCESSING
```{r}
# Check the structure of each dataset
str(portfolio)
str(profile)
str(transcript)
# Check summary statistics
summary(portfolio)
summary(profile)
summary(transcript)
# Check for missing values
sum(is.na(portfolio))
sum(is.na(profile))
sum(is.na(transcript))
```
```{r}
# PORTFOLIO DATA
# Clean up 'channels' column
portfolio$channels <- gsub("\\[|\\]|'", "", portfolio$channels)
# Convert 'channels' to a list
portfolio$channels <- lapply(strsplit(portfolio$channels, ","), trimws)
# Extract unique channels
unique_channels <- unique(unlist(portfolio$channels))
# Create binary columns for each channel
for (channel in unique_channels) {
# Remove leading and trailing spaces
cleaned_channel <- trimws(channel)
# Create binary columns for each cleaned channel
portfolio[paste0("channel_", cleaned_channel)] <- as.integer(sapply(portfolio$channels, function(x) cleaned_channel %in% x))
}
portfolio
```
```{r}
# PROFILE
# Convert 'gender' to factor
profile$gender <- as.factor(profile$gender)
# Impute missing values in 'income' with mean
profile$income[is.na(profile$income)] <- mean(profile$income, na.rm = TRUE)
# Check unique values in 'became_member_on' to identify any issues
unique(profile$became_member_on)
# Remove any non-numeric characters
profile$became_member_on <- gsub("[^0-9]", "", profile$became_member_on)
# Convert 'became_member_on' to Date
profile$became_member_on <- as.Date(profile$became_member_on, format = "%Y%m%d")
head(profile)
```
```{r}
head(transcript)
```
```{r}
# TRANSCRIPT
# Load the jsonlite library
library(jsonlite)
# Extract offer id from 'value' column
transcript$value <- gsub("'", "\"", transcript$value) # Replace single quotes with double quotes
transcript$offer_id <- sapply(transcript$value, function(x) {
parsed_value <- fromJSON(x, simplifyVector = TRUE)
if (!is.null(parsed_value) && 'offer id' %in% names(parsed_value)) {
return(parsed_value[['offer id']])
} else {
return(NA)
}
})
# Drop the 'value' column as we've extracted the offer id
transcript <- subset(transcript, select = -c(value))
```
```{r}
head(transcript)
```
## FEATURE ENTINEERING
```{r}
# FE PROFILE
# Calculate membership duration in days
profile$membership_duration <- as.numeric(difftime(Sys.Date(), profile$became_member_on, units = "days"))
head(profile)
```
```{r}
# FE TRANSCRIPT
head(transcript)
# Create binary columns for different events
transcript$offer_received <- as.integer(transcript$event == "offer received")
transcript$offer_viewed <- as.integer(transcript$event == "offer viewed")
transcript$offer_completed <- as.integer(transcript$event == "offer completed")
transcript$transaction <- as.integer(transcript$event == "transaction")
```
```{r}
head(transcript)
```
## MERGING DATA
```{r}
# Merge profile and transcript datasets based on 'id' (customer ID)
merged_data <- merge(profile, transcript, by.x = "id", by.y = "person", all.x = TRUE)
# Merge the resulting dataset with the portfolio dataset based on 'offer_id'
merged_data <- merge(merged_data, portfolio, by.x = "offer_id", by.y = "id", all.x = TRUE)
# Check the structure and summary of the merged dataset
str(merged_data)
summary(merged_data)
```
```{r}
merged_data
```
## K-MEANS CLUSTERING
```{r}
# Select relevant features for clustering
features_for_clustering <- merged_data[, c("age", "income", "membership_duration", "reward", "difficulty", "duration")]
# Check for missing values
if (any(sapply(features_for_clustering, function(x) any(is.na(x))))) {
# Impute missing values with mean
features_for_clustering <- lapply(features_for_clustering, function(x) {
x[is.na(x)] <- mean(x, na.rm = TRUE)
x
})
}
# Convert the list to a data frame
features_for_clustering <- as.data.frame(features_for_clustering)
# Check for infinite values
if (any(sapply(features_for_clustering, function(x) any(!is.finite(x))))) {
# Replace infinite values with appropriate values or investigate the cause
features_for_clustering <- lapply(features_for_clustering, function(x) {
x[!is.finite(x)] <- 0
x
})
}
# Standardize the features after handling missing and infinite values
scaled_features <- scale(features_for_clustering)
# Check for missing or infinite values after scaling
any(is.na(scaled_features))
any(!is.finite(scaled_features))
```
```{r}
# Elbow Method to find the optimal number of clusters
wss <- numeric(4) # Set the maximum number of clusters you want to try (e.g., 10)
for (i in 1:4) {
kmeans_result <- kmeans(scaled_features, centers = i)
wss[i] <- kmeans_result$tot.withinss
}
# Plot the elbow curve
plot(1:4, wss, type = "b", pch = 19, frame = FALSE,
xlab = "Number of Clusters", ylab = "Total Within-Cluster Sum of Squares",
main = "Elbow Method")
# Add a line at the "elbow" or optimal number of clusters
abline(v = which.min(wss), col = "red", lty = 2)
# Print the optimal number of clusters
cat("Optimal Number of Clusters:", which.min(wss), "\n")
```
```{r}
# Example: K-means clustering with k clusters
k <- 4 # Replace with your desired number of clusters
kmeans_result <- kmeans(scaled_features, centers = k)
# View the clustering results
str(kmeans_result)
# Assign cluster labels to each observation in your data
merged_data$cluster <- kmeans_result$cluster
# Check the distribution of clusters
table(merged_data$cluster)
# Explore the characteristics of each cluster
cluster_summary <- aggregate(. ~ cluster, data = merged_data[, c("cluster", "age", "income", "membership_duration", "reward", "difficulty", "duration")], mean)
print(cluster_summary)
```
```{r}
# Bar plot of cluster distribution
barplot(table(merged_data$cluster), main = "Cluster Distribution", xlab = "Cluster", ylab = "Count", col = rainbow(k))
```
```{r}
```
```{r}
```
```{r}
```
```{r}
```
```{r}
```
```{r}
```
```{r}
```
```{r}
```