Dataset and Sampling Method

The Mall Customer Segmentation dataset is a marketing-related dataset containing customer demographics, annual income, and spending scores.

mall <- read_csv("Mall_Customers.csv", show_col_types = FALSE)

original_n <- nrow(mall)

set.seed(3010)
sample_data <- mall %>%
  slice_sample(n = floor(original_n / 2))

cat("Original sample size:", original_n, "\n")
## Original sample size: 200
cat("Sample size used:", nrow(sample_data), "\n")
## Sample size used: 100

The original dataset contains 200 observations. I used 100 observations, which represents exactly half of the original dataset.

Calculation:

nrow(sample_data) / original_n
## [1] 0.5

Exploratory Data Analysis One

Spending Score Distribution

sample_data %>%
  summarise(
    n = n(),
    mean = mean(`Spending Score (1-100)`),
    median = median(`Spending Score (1-100)`),
    standard_deviation = sd(`Spending Score (1-100)`),
    minimum = min(`Spending Score (1-100)`),
    maximum = max(`Spending Score (1-100)`)
  )
## # A tibble: 1 × 6
##       n  mean median standard_deviation minimum maximum
##   <int> <dbl>  <dbl>              <dbl>   <dbl>   <dbl>
## 1   100  52.4     49               21.9       4      92
ggplot(sample_data, aes(x = `Spending Score (1-100)`)) +
  geom_histogram(
    binwidth = 10,
    boundary = 0,
    fill = "#2F6F8F",
    color = "white"
  ) +
  geom_vline(
    aes(xintercept = mean(`Spending Score (1-100)`)),
    color = "#C95C3B",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Spending Scores",
    x = "Spending Score",
    y = "Number of Customers"
  ) +
  theme_minimal()

Exploratory Data Analysis Two

Annual Income and Spending Score

cor(
  sample_data$`Annual Income (k$)`,
  sample_data$`Spending Score (1-100)`
)
## [1] 0.10092
ggplot(
  sample_data,
  aes(
    x = `Annual Income (k$)`,
    y = `Spending Score (1-100)`,
    color = Gender
  )
) +
  geom_point(alpha = 0.8) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = "black"
  ) +
  labs(
    title = "Annual Income and Spending Score",
    x = "Annual Income in Thousands of Dollars",
    y = "Spending Score"
  ) +
  theme_minimal()

Cross Tabulation

sample_data %>%
  mutate(
    income_band = cut(
      `Annual Income (k$)`,
      breaks = c(0, 40, 70, 100, 140),
      labels = c(
        "$15-$40k",
        "$41-$70k",
        "$71-$100k",
        "$101-$137k"
      )
    ),
    spending_band = cut(
      `Spending Score (1-100)`,
      breaks = c(0, 39, 69, 100),
      labels = c(
        "Low",
        "Moderate",
        "High"
      )
    )
  ) %>%
  count(income_band, spending_band) %>%
  pivot_wider(
    names_from = spending_band,
    values_from = n,
    values_fill = 0
  )
## # A tibble: 4 × 4
##   income_band   Low Moderate  High
##   <fct>       <int>    <int> <int>
## 1 $15-$40k        9        5     6
## 2 $41-$70k       14       21    10
## 3 $71-$100k      10        9     8
## 4 $101-$137k      1        2     5

What I Learned

The sample contains customers with a wide range of spending scores, meaning the customers are not all one uniform market. Annual income and spending score have little or no linear relationship in this sample. Therefore, marketers should combine income with other characteristics such as age, gender, purchase history, and promotion response.

Source

Kaggle Mall Customers Dataset:

https://www.kaggle.com/datasets/kandij/mall-customers