Phần 1: Tìm hiểu và Chuẩn bị Dữ liệu

Bộ dữ liệu được sử dụng trong báo cáo này bao gồm thông tin của 3.900 cá nhân, phản ánh một số đặc điểm nhân khẩu học và hành vi mua sắm cơ bản của người tiêu dùng. Các biến trong dữ liệu bao gồm giới tính (Gender), nhóm tuổi (Age Group). Đặc biệt, dữ liệu còn ghi nhận trạng thái đăng ký thành viên (Subscription Status) – một chỉ báo quan trọng liên quan đến mức độ gắn kết của khách hàng với hệ thống bán lẻ.

#Đọc dữ liệu
a <- read.csv("C:/Users/Admin/Desktop/Shopping_Habit.csv", 
                 header = TRUE, sep = ",")
#cấu trúc của dữ liệu 
str(a)
## 'data.frame':    3900 obs. of  18 variables:
##  $ Customer.ID           : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Age                   : int  55 19 50 21 45 46 63 27 26 57 ...
##  $ Gender                : chr  "Male" "Male" "Male" "Male" ...
##  $ Item.Purchased        : chr  "Blouse" "Sweater" "Jeans" "Sandals" ...
##  $ Category              : chr  "Clothing" "Clothing" "Clothing" "Footwear" ...
##  $ Purchase.Amount..USD. : int  53 64 73 90 49 20 85 34 97 31 ...
##  $ Location              : chr  "Kentucky" "Maine" "Massachusetts" "Rhode Island" ...
##  $ Size                  : chr  "L" "L" "S" "M" ...
##  $ Color                 : chr  "Gray" "Maroon" "Maroon" "Maroon" ...
##  $ Season                : chr  "Winter" "Winter" "Spring" "Spring" ...
##  $ Review.Rating         : num  3.1 3.1 3.1 3.5 2.7 2.9 3.2 3.2 2.6 4.8 ...
##  $ Subscription.Status   : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Shipping.Type         : chr  "Express" "Express" "Free Shipping" "Next Day Air" ...
##  $ Discount.Applied      : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Promo.Code.Used       : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Previous.Purchases    : int  14 2 23 49 31 14 49 19 8 4 ...
##  $ Payment.Method        : chr  "Venmo" "Cash" "Credit Card" "PayPal" ...
##  $ Frequency.of.Purchases: chr  "Fortnightly" "Fortnightly" "Weekly" "Weekly" ...

Bộ dữ liệu thực hành gồm 3900 quan sát, trong đó bao gồm 18 biến. Cụ thể như sau:

CustomerID: Mã định danh duy nhất của khách hàng, dùng để theo dõi và phân biệt từng cá nhân trong cơ sở dữ liệu, hỗ trợ phân tích hành vi khách hàng.

Age: Thể hiện độ tuổi – dùng để phân khúc khách hàng và xây dựng chiến lược marketing theo độ tuổi.

Gender: Giới tính của khách hàng (ví dụ: Nam, Nữ), giúp đánh giá sự khác biệt trong sở thích mua sắm giữa các nhóm giới tính.

Item Purchased: Tên sản phẩm cụ thể khách hàng đã chọn trong lần mua.

Category: Nhóm sản phẩm lớn hơn (như điện tử, quần áo…) giúp phân loại và phân tích xu hướng tiêu dùng.

Purchase Amount (USD): Giá trị tiền tệ của giao dịch, dùng để phân tích chi tiêu.

Location: Vị trí nơi mua hàng – giúp theo dõi thói quen theo vùng miền.

Size: Kích thước của sản phẩm (áp dụng với quần áo, giày dép…)

Color: Màu sắc sản phẩm, Tùy chọn màu của sản phẩm, phản ánh thị hiếu màu sắc.

Season: Mùa liên quan đến sản phẩm (xuân/hạ/thu/đông), ảnh hưởng đến chiến lược tồn kho và tiếp thị.

Review Rating: Đánh giá từ khách hàng.

Subscription Status: Trạng thái đăng ký, Khách hàng có sử dụng dịch vụ đăng ký không, thể hiện mức độ trung thành.

Shipping Type: Loại hình vận chuyển.

Discount Applied: Có áp dụng giảm giá không.

Promo Code Used: Cho biết khách hàng có dùng mã ưu đãi trong giao dịch hay không.

Previous Purchases: Số lượng lần mua trong quá khứ.

Payment Method: Phương thức thanh toán.

Frequency of Purchases: Tần suất mua hàng.

head(a)#Hiển thị một vài dòng đầu
tail(a)#Hiển thị một vài dòng cuối

Kết quả trên hiển thị 6 dòng đầu và 6 dòng cuối của dữ liệu.

# Chọn các biến định tính
a1 <- c("Gender","Item.Purchased", "Category","Location", "Size", "Color", "Season", 
        "Subscription.Status", "Discount.Applied", "Promo.Code.Used",  "Payment.Method" ,  "Frequency.of.Purchases" )
print(a1)
##  [1] "Gender"                 "Item.Purchased"         "Category"              
##  [4] "Location"               "Size"                   "Color"                 
##  [7] "Season"                 "Subscription.Status"    "Discount.Applied"      
## [10] "Promo.Code.Used"        "Payment.Method"         "Frequency.of.Purchases"
# Tạo bộ dữ liệu mới chỉ chứa các biến định tính
b <- a[, a1]
str(b)
## 'data.frame':    3900 obs. of  12 variables:
##  $ Gender                : chr  "Male" "Male" "Male" "Male" ...
##  $ Item.Purchased        : chr  "Blouse" "Sweater" "Jeans" "Sandals" ...
##  $ Category              : chr  "Clothing" "Clothing" "Clothing" "Footwear" ...
##  $ Location              : chr  "Kentucky" "Maine" "Massachusetts" "Rhode Island" ...
##  $ Size                  : chr  "L" "L" "S" "M" ...
##  $ Color                 : chr  "Gray" "Maroon" "Maroon" "Maroon" ...
##  $ Season                : chr  "Winter" "Winter" "Spring" "Spring" ...
##  $ Subscription.Status   : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Discount.Applied      : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Promo.Code.Used       : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Payment.Method        : chr  "Venmo" "Cash" "Credit Card" "PayPal" ...
##  $ Frequency.of.Purchases: chr  "Fortnightly" "Fortnightly" "Weekly" "Weekly" ...

Trong phạm vi bài làm này, chỉ thực hiện thao tác với các biến định tính bao gồm: Gender, Item Purchase, Category, Location, Size, Color, Season, Subscription Status”, Discount Applied, Promo CodeUsed, Payment Method , Frequency of Purchases.

Tiếp theo, em tiến hành Kiểm tra xem có giá trị thiếu (NA) trong các cột định tính hay không.

#Kiểm tra xem có giá trị thiếu (NA) trong các cột định tính
colSums(is.na(b))
##                 Gender         Item.Purchased               Category 
##                      0                      0                      0 
##               Location                   Size                  Color 
##                      0                      0                      0 
##                 Season    Subscription.Status       Discount.Applied 
##                      0                      0                      0 
##        Promo.Code.Used         Payment.Method Frequency.of.Purchases 
##                      0                      0                      0

Tất cả các cột định tính trong dataframe b đều có giá trị 0 cho số lượng giá trị thiếu (NA). Điều này có nghĩa là không có giá trị NA trong các cột định tính của bộ dữ liệu b.

Trước khi tiến hành các phân tích thống kê, việc chuyển đổi các biến định tính từ kiểu ký tự (character) sang kiểu phân loại (factor) là cần thiết nhằm đảm bảo rằng các hàm thống kê và mô hình phân tích sẽ xử lý chúng đúng cách. Trong R, các biến factor không chỉ giúp biểu diễn dữ liệu phân loại một cách chính xác hơn mà còn tối ưu hóa hiệu suất tính toán và cho phép áp dụng các phương pháp phân tích định tính như kiểm định Chi-bình phương hay mô hình hồi quy phân loại. Việc kiểm tra và xử lý kiểu dữ liệu phù hợp là bước tiền xử lý quan trọng, góp phần đảm bảo tính chính xác và hiệu quả của toàn bộ quy trình phân tích.

# Kiểm tra từng cột trong dataframe b
sapply(b, is.factor)
##                 Gender         Item.Purchased               Category 
##                  FALSE                  FALSE                  FALSE 
##               Location                   Size                  Color 
##                  FALSE                  FALSE                  FALSE 
##                 Season    Subscription.Status       Discount.Applied 
##                  FALSE                  FALSE                  FALSE 
##        Promo.Code.Used         Payment.Method Frequency.of.Purchases 
##                  FALSE                  FALSE                  FALSE

Kết quả là FALSE, vậy các biến cần thiết không phải kiểu factor. Vì vậy, bước tiếp t sẽ thực hiện Chuyển đổi các cột character sang factor.

# Chuyển đổi các cột character sang factor
b$Gender <- as.factor(b$Gender)
b$Item.Purchased <- as.factor(b$Item.Purchased)
b$Category <- as.factor(b$Category)
b$Location <- as.factor(b$Location)
b$Size <- as.factor(b$Size)
b$Color <- as.factor(b$Color)
b$Season <- as.factor(b$Season)

b$Subscription.Status <- as.factor(b$Subscription.Status)
b$Discount.Applied<- as.factor(b$Discount.Applied)
b$Promo.Code.Used<- as.factor(b$Promo.Code.Used)
b$Payment.Method<- as.factor(b$Payment.Method)
b$Frequency.of.Purchases<- as.factor(b$Frequency.of.Purchases)
#kiểm tra lại
sapply(b, is.factor)
##                 Gender         Item.Purchased               Category 
##                   TRUE                   TRUE                   TRUE 
##               Location                   Size                  Color 
##                   TRUE                   TRUE                   TRUE 
##                 Season    Subscription.Status       Discount.Applied 
##                   TRUE                   TRUE                   TRUE 
##        Promo.Code.Used         Payment.Method Frequency.of.Purchases 
##                   TRUE                   TRUE                   TRUE

Tất cả các biến sau khi chuyển đổi đều cho kết quả TRUE, nghĩa là việc chuyển đổi thành công và các biến đã sẵn sàng cho phân tích thống kê phù hợp với bản chất định tính của chúng. Điều này đảm bảo độ chính xác và hiệu quả khi áp dụng các phương pháp thống kê phân tích dữ liệu định tính trong các bước tiếp theo.

Phần 2: Phân tích Mô tả Một biến Định tính (Univariate Descriptive Analysis)

1.Thống kê mô tả biến Gender

Thống kê Tần suất

# Tính tần số và tần suất
Gender_freq <- table(b$Gender)
Gender_prop <- table(b$Gender) / sum(nrow(b)) 
print(Gender_freq)
## 
## Female   Male 
##   1248   2652
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo dataframe cho bảng
table_data <- data.frame(
  `Giới tính` = c("Nữ", "Nam"),
  `Tần số` = as.numeric(Gender_freq),
  `Tần suất (%)` = round(Gender_prop * 100, 2)
)
colnames(table_data) <- c("Giới tính", "Tần số", "Kí hiệu", "Tần suất (%)")
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Giới tính Tần số Kí hiệu Tần suất (%)
Nữ 1248 Female 32
Nam 2652 Male 68

Kết quả cho thấy sự phân phối khá cân đối giữa các nhóm. Cụ thể, tỷ lệ khách hàng nam và nữ chênh lệch khá lớn, với nữ chiếm 0.32 và nam chiếm 0.68, chỉ chênh lệch khoảng -0.36.

Trực quan hóa

# Tạo biểu đồ cột và lưu vị trí
bar_positions <- barplot(Gender_freq, 
                         main = "Phân phối khách hàng theo giới tính",
                         xlab = "Giới tính",
                         ylab = "Số lượng giao dịch",
                         col = c("#CC99FF", "#FFFF33"),  
                         names.arg = c("Nữ", "Nam"),
                         ylim = c(0, max(Gender_freq) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions, 
     y = Gender_freq + 500,  # Tăng khoảng cách nhãn lên 500 để hiển thị rõ
     labels = Gender_freq,  # Giá trị tần suất
     pos = 3,  # Đặt nhãn phía trên cột
     col = "black",  # Màu chữ đen
     cex = 1.2)  # Kích thước chữ lớn hơn

Biểu đồ cột mang tên “Phân phối khách hàng theo giới tính” được trình bày ở trên cung cấp một cái nhìn sơ bộ về sự phân bố số lượng giao dịch theo hai nhóm giới tính. Cụ thể, nam giới chiếm 68% tổng số giao dịch, trong khi nữ giới chỉ chiếm 32%. Điều này cho thấy nam giới là nhóm khách hàng chính, có xu hướng mua sắm nhiều hơn hoặc xuất hiện nhiều hơn trong tập dữ lu. Sự chênh lệch này có thể phản ánh đặc điểm của thị trường mục tiêu, chiến lược tiếp thị hiện tại. Do đó, doanh nghiệp nên xem xét lý do dẫn đến sự mất cân đối này và cân nhắc các chiến lược tiếp cận nhóm khách hàng nữ để mở rộng thị phần và tăng trưởng doanh thu hiệu quả hơn.

2.Thống kê mô tả biến Item Purchased

Thống kê Tần suất

# Tính tần số và tần suất
Item.Purchase_freq <- table(b$Item.Purchased)
Item.Purchase_prop <- table(b$Item.Purchased) / sum(nrow(b)) 
# Tính tần số và tần suất
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo dataframe cho bảng
# Tạo dataframe cho bảng
table_data2 <- data.frame(
  `Tình trạng` = names(Item.Purchase_freq),
  `Tần số` = as.numeric(Item.Purchase_freq),
  `Tần suất (%)` = round(Item.Purchase_prop * 100, 2)
)
colnames(table_data2) <- c("Mặt hàng","Tần số","Mặt hàng", "Tần suất (%)")
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data2, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Mặt hàng Tần số Mặt hàng Tần suất (%)
Backpack 143 Backpack 3.67
Belt 161 Belt 4.13
Blouse 171 Blouse 4.38
Boots 144 Boots 3.69
Coat 161 Coat 4.13
Dress 166 Dress 4.26
Gloves 140 Gloves 3.59
Handbag 153 Handbag 3.92
Hat 154 Hat 3.95
Hoodie 151 Hoodie 3.87
Jacket 163 Jacket 4.18
Jeans 124 Jeans 3.18
Jewelry 171 Jewelry 4.38
Pants 171 Pants 4.38
Sandals 160 Sandals 4.10
Scarf 157 Scarf 4.03
Shirt 169 Shirt 4.33
Shoes 150 Shoes 3.85
Shorts 157 Shorts 4.03
Skirt 158 Skirt 4.05
Sneakers 145 Sneakers 3.72
Socks 159 Socks 4.08
Sunglasses 161 Sunglasses 4.13
Sweater 164 Sweater 4.21
T-shirt 147 T-shirt 3.77

Trực quan hóa

# Tạo biểu đồ cột và lưu vị trí
bar_positions2 <- barplot(Item.Purchase_freq, 
                         main = "Phân phối khách hàng theo mặt hàng đã mua",
                         xlab = "Mặt hàng",
                         ylab = "Số lượng giao dịch",
                         col = c("#99FFFF", "#CCCCFF"), 
                         names.arg = names(Item.Purchase_freq),
                         ylim = c(0, max(Item.Purchase_freq) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions2, 
     y = Item.Purchase_freq + 500,  # Tăng khoảng cách nhãn lên 500 để hiển thị rõ
     labels = Item.Purchase_freq,  # Giá trị tần suất
     pos = 3,  # Đặt nhãn phía trên cột
     col = "black",  # Màu chữ đen
     cex = 1.2)  # Kích thước chữ lớn hơn

Kết quả trên cho thấy sự phân bố tương đối đồng đều giữa các mặt hàng thời trang. Các mặt hàng như Jewelry, Pants và Blouse có tần suất cao nhất (4.38%), cho thấy chúng được ưa chuộng nhiều hơn. Shirt và Dress cũng có tỷ lệ mua cao (trên 4.2%). Ngược lại, các sản phẩm như Jeans, Gloves và Backpack có tần suất thấp hơn (dưới 3.7%), cho thấy nhu cầu ít hơn. Nhìn chung, không có mặt hàng nào chiếm tỷ lệ vượt trội, phản ánh sự đa dạng trong sở thích tiêu dùng của khách hàng. Điều này gợi ý rằng doanh nghiệp nên duy trì danh mục sản phẩm phong phú để đáp ứng các nhu cầu khác nhau của thị trường.

3.Thống kê mô tả biến Category

Thống kê Tần suất

# Tính tần số và tần suất
category_freq <- table(b$Category)
category_prop <- table(b$Category) / sum(nrow(b)) 
print(category_freq)
## 
## Accessories    Clothing    Footwear   Outerwear 
##        1240        1737         599         324
# Tạo dataframe cho bảng
table_data3 <- data.frame(
   `Danh mục` = names(category_freq),
  `Tần số` = as.numeric(category_freq),
  `Tần suất (%)` = round(category_prop * 100, 2)
)

colnames(table_data3) <- c("Danh mục", "Tần số", "Danh mục", "Tần suất (%)")
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data3, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Danh mục Tần số Danh mục Tần suất (%)
Accessories 1240 Accessories 31.79
Clothing 1737 Clothing 44.54
Footwear 599 Footwear 15.36
Outerwear 324 Outerwear 8.31

Trực quan hóa

# Tạo bảng màu (đủ cho số danh mục)
num_categories <- length(category_freq)
colors <- c("#0066CC", "#00CC99", "#FF6666", "#FFCC00")[1:num_categories]  # Chọn màu đủ
# Tạo biểu đồ cột và lưu vị trí
bar_positions3 <- barplot(category_freq, 
                          main = "Phân phối khách hàng theo danh mục sản phẩm",  # Thêm main =
                          xlab = "Danh mục sản phẩm",
                          ylab = "Số lượng giao dịch",
                          col = colors,  # Biến colors đã định nghĩa
                          names.arg = names(category_freq),  # Sử dụng tên danh mục
                          ylim = c(0, max(category_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions3, 
     y = category_freq + max(category_freq, na.rm = TRUE) * 0.05,  # Khoảng cách động
     labels = category_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 1.2)  # Kích thước chữ

Kết quả cho thấy Clothing (Trang phục) là danh mục được ưa chuộng nhất, chiếm 44.54% tổng số giao dịch. Điều này phản ánh xu hướng tiêu dùng tập trung mạnh vào các sản phẩm cơ bản và thiết yếu. Accessories (Phụ kiện) đứng thứ hai với 31.79%, cho thấy vai trò quan trọng của các mặt hàng bổ trợ trong hành vi mua sắm của khách hàng. Trong khi đó, Footwear (Giày dép) và Outerwear (Áo khoác, áo choàng) lần lượt chiếm 15.36% và 8.31%, có thể do ảnh hưởng bởi yếu tố thời tiết, nhu cầu theo mùa hoặc mức giá cao hơn. Nhìn chung, hơn 76% các sản phẩm được mua thuộc về nhóm Clothing và Accessories.

4.Thống kê mô tả biến Locatione

Thống kê Tần suất

# Tính tần số và tần suất
Location_freq <- table(b$Location)
Location_prop <- table(b$Location) / sum(nrow(b)) 
print(Location_freq)
## 
##        Alabama         Alaska        Arizona       Arkansas     California 
##             89             72             65             79             95 
##       Colorado    Connecticut       Delaware        Florida        Georgia 
##             75             78             86             68             79 
##         Hawaii          Idaho       Illinois        Indiana           Iowa 
##             65             93             92             79             69 
##         Kansas       Kentucky      Louisiana          Maine       Maryland 
##             63             79             84             77             86 
##  Massachusetts       Michigan      Minnesota    Mississippi       Missouri 
##             72             73             88             80             81 
##        Montana       Nebraska         Nevada  New Hampshire     New Jersey 
##             96             87             87             71             67 
##     New Mexico       New York North Carolina   North Dakota           Ohio 
##             81             87             78             83             77 
##       Oklahoma         Oregon   Pennsylvania   Rhode Island South Carolina 
##             75             74             74             63             76 
##   South Dakota      Tennessee          Texas           Utah        Vermont 
##             70             77             77             71             85 
##       Virginia     Washington  West Virginia      Wisconsin        Wyoming 
##             77             73             81             75             71
# Tạo dataframe cho bảng
table_data4 <- data.frame(
  `Địa điểm` = names(Location_freq),
  `Tần số` = as.numeric(Location_freq),
  `Tần suất (%)` = round(Location_prop * 100, 2)
)
colnames(table_data4) <- c("Địa điểm", "Tần số", "Địa điểm", "Tần suất (%)")
# Tạo bảng kẻ
# Tạo bảng kẻ
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
library(knitr)
library(kableExtra)

kable(table_data4, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Địa điểm Tần số Địa điểm Tần suất (%)
Alabama 89 Alabama 2.28
Alaska 72 Alaska 1.85
Arizona 65 Arizona 1.67
Arkansas 79 Arkansas 2.03
California 95 California 2.44
Colorado 75 Colorado 1.92
Connecticut 78 Connecticut 2.00
Delaware 86 Delaware 2.21
Florida 68 Florida 1.74
Georgia 79 Georgia 2.03
Hawaii 65 Hawaii 1.67
Idaho 93 Idaho 2.38
Illinois 92 Illinois 2.36
Indiana 79 Indiana 2.03
Iowa 69 Iowa 1.77
Kansas 63 Kansas 1.62
Kentucky 79 Kentucky 2.03
Louisiana 84 Louisiana 2.15
Maine 77 Maine 1.97
Maryland 86 Maryland 2.21
Massachusetts 72 Massachusetts 1.85
Michigan 73 Michigan 1.87
Minnesota 88 Minnesota 2.26
Mississippi 80 Mississippi 2.05
Missouri 81 Missouri 2.08
Montana 96 Montana 2.46
Nebraska 87 Nebraska 2.23
Nevada 87 Nevada 2.23
New Hampshire 71 New Hampshire 1.82
New Jersey 67 New Jersey 1.72
New Mexico 81 New Mexico 2.08
New York 87 New York 2.23
North Carolina 78 North Carolina 2.00
North Dakota 83 North Dakota 2.13
Ohio 77 Ohio 1.97
Oklahoma 75 Oklahoma 1.92
Oregon 74 Oregon 1.90
Pennsylvania 74 Pennsylvania 1.90
Rhode Island 63 Rhode Island 1.62
South Carolina 76 South Carolina 1.95
South Dakota 70 South Dakota 1.79
Tennessee 77 Tennessee 1.97
Texas 77 Texas 1.97
Utah 71 Utah 1.82
Vermont 85 Vermont 2.18
Virginia 77 Virginia 1.97
Washington 73 Washington 1.87
West Virginia 81 West Virginia 2.08
Wisconsin 75 Wisconsin 1.92
Wyoming 71 Wyoming 1.82

Trực quan hóa

# Tạo bảng màu (đủ cho số địa điểm)
num_locations <- length(Location_freq)
colors <- rainbow(num_locations, s = 0.6)  # Tạo màu động, nhạt hơn để dễ nhìn
# Tạo biểu đồ cột và lưu vị trí
bar_positions4 <- barplot(Location_freq, 
                          main = "Phân phối khách hàng theo địa điểm",
                          xlab = "Địa điểm",
                          ylab = "Số lượng giao dịch",
                          col = colors, 
                          names.arg = names(Location_freq),  # Sử dụng tên địa điểm
                          las = 2,  # Xoay nhãn trục x 90 độ để tránh chồng lấn
                          cex.names = 0.6,  # Giảm kích thước nhãn vì nhiều địa điểm
                          ylim = c(0, max(Location_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions4, 
     y = Location_freq + 500,  # Tăng khoảng cách nhãn lên 500 để hiển thị rõ
     labels = Location_freq,  # Giá trị tần suất
     pos = 3,  # Đặt nhãn phía trên cột
     col = "black",  # Màu chữ đen
     cex = 0.8)  # Kích thước chữ nhỏ hơn do nhiều cột

Kết quả phân bố tần suất theo địa phương phản ánh một sự phân bổ tương đối đồng đều về hoạt động mua sắm của khách hàng trên toàn lãnh thổ Hoa Kỳ. Mặc dù không có sự chênh lệch cực đoan nào, một số bang nổi bật với tỷ lệ mua sắm cao hơn trung bình, điển hình như Montana (2.46%), California (2.44%), Idaho (2.38%) và Illinois (2.36%). Những địa phương này có thể đang sở hữu các điều kiện thuận lợi như mật độ dân số cao, thu nhập ổn định hoặc hạ tầng thương mại phát triển, từ đó tạo nên sức mua lớn hơn so với mặt bằng chung.

Ngược lại, các bang như Kansas (1.62%) và Rhode Island (1.62%) lại cho thấy tần suất giao dịch tương đối thấp, có thể là do quy mô dân số nhỏ hơn hoặc mức độ thâm nhập thị trường của doanh nghiệp chưa sâu rộng. Tuy vậy, sự hiện diện của khách hàng ở hầu hết các bang cho thấy mức độ lan tỏa toàn quốc của thương hiệu hoặc nền tảng phân phối, mở ra tiềm năng cho các chiến lược cá nhân hóa theo vùng hoặc tối ưu hóa mạng lưới cung ứng.

5.Thống kê mô tả biến Size

Thống kê Tần suất

# Tính tần số và tần suất
size_freq <- table(b$Size)
size_prop <- table(b$Size) / sum(nrow(b)) 
print(size_freq)
## 
##    L    M    S   XL 
## 1053 1755  663  429
# Tạo dataframe cho bảng
table_data5 <- data.frame(
  `Kích cỡ` = names(size_freq),
  `Tần số` = as.numeric(size_freq),
  `Tần suất (%)` = round(size_prop * 100, 2)
)
colnames(table_data5) <- c("Kích cỡ", "Tần số", "Kích cỡ", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data5, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Kích cỡ Tần số Kích cỡ Tần suất (%)
L 1053 L 27
M 1755 M 45
S 663 S 17
XL 429 XL 11

Trực quan hóa

# Tạo bảng màu (cố định cho số kích cỡ)
num_sizes <- length(size_freq)
colors <- c("#0066CC", "#00CC99", "#FF6666", "#FFCC00")[1:num_sizes]  # Chọn màu đủ

# Tạo biểu đồ cột
bar_positions5 <- barplot(size_freq, 
                          main = "Phân phối khách hàng theo kích cỡ",
                          xlab = "Kích cỡ",
                          ylab = "Số lượng giao dịch",
                          col = colors,  # Sử dụng bảng màu cố định
                          names.arg = names(size_freq),  # Sử dụng tên kích cỡ
                          las = 1,  # Nhãn trục x nằm ngang (ít giá trị)
                          cex.names = 0.9,  # Kích thước nhãn trục x phù hợp
                          ylim = c(0, max(size_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%
# Thêm nhãn số trên mỗi cột
text(x = bar_positions5, 
     y = size_freq + max(size_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = size_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.8)  # Kích thước chữ nhỏ hơn

Bảng phân bố tần suất theo kích cỡ cho thấy kích cỡ M (Trung bình) chiếm ưu thế rõ rệt với 45% tổng số lượng sản phẩm được mua, cho thấy đây là kích cỡ phổ biến và được ưa chuộng nhất trong nhóm khách hàng hiện tại. Tiếp theo là kích cỡ L với 27%, cho thấy sự quan tâm không nhỏ đến phân khúc khách hàng có vóc dáng lớn hơn trung bình.

Trong khi đó, kích cỡ S chiếm 17%, phản ánh một bộ phận khách hàng nhỏ hơn, có thể là thanh thiếu niên, người có vóc dáng nhỏ, hoặc phụ nữ. Kích cỡ XL chỉ chiếm 11%, cho thấy nhu cầu ở phân khúc kích cỡ lớn hơn là có nhưng tương đối hạn chế.

6.Thống kê mô tả biến Color

Thống kê Tần suất

# Tính tần số và tần suất
color_freq <- table(b$Color)
color_prop <- table(b$Color) / sum(nrow(b)) 
print(color_freq)
## 
##     Beige     Black      Blue     Brown      Cyan  Charcoal      Gold      Gray 
##       147       167       152       141       166       153       138       159 
##     Green    Indigo  Lavender   Magenta    Maroon     Olive    Orange     Peach 
##       169       147       147       152       158       177       154       149 
##      Pink    Purple       Red    Silver      Teal Turquoise    Violet     White 
##       153       151       148       173       172       145       166       142 
##    Yellow 
##       174
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo dataframe cho bảng
table_data6 <- data.frame(
  `Màu sắc` = names(color_freq),
  `Tần số` = as.numeric(color_freq),
  `Tần suất (%)` = round(color_prop * 100, 2)
)
colnames(table_data6) <- c("Màu sắc", "Tần số", "Màu sắc", "Tần suất (%)")


# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data6, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Màu sắc Tần số Màu sắc Tần suất (%)
Beige 147 Beige 3.77
Black 167 Black 4.28
Blue 152 Blue 3.90
Brown 141 Brown 3.62
Cyan 166 Cyan 4.26
Charcoal 153 Charcoal 3.92
Gold 138 Gold 3.54
Gray 159 Gray 4.08
Green 169 Green 4.33
Indigo 147 Indigo 3.77
Lavender 147 Lavender 3.77
Magenta 152 Magenta 3.90
Maroon 158 Maroon 4.05
Olive 177 Olive 4.54
Orange 154 Orange 3.95
Peach 149 Peach 3.82
Pink 153 Pink 3.92
Purple 151 Purple 3.87
Red 148 Red 3.79
Silver 173 Silver 4.44
Teal 172 Teal 4.41
Turquoise 145 Turquoise 3.72
Violet 166 Violet 4.26
White 142 White 3.64
Yellow 174 Yellow 4.46

Trực quan hóa

# Tạo biểu đồ cột
bar_positions6 <- barplot(color_freq, 
                          main = "Phân phối khách hàng theo màu sắc",
                          xlab = "Màu sắc",
                          ylab = "Số lượng giao dịch",
                          col =rainbow(length(color_freq)),  # Sử dụng bảng màu cố định
                          names.arg = names(color_freq),  # Sử dụng tên màu
                          las = 2,  # Xoay nhãn trục x 90 độ để dễ đọc
                          cex.names = 0.8,  # Kích thước nhãn trục x
                          ylim = c(0, max(color_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions6, 
     y = color_freq + max(color_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = color_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.9)  # Kích thước chữ

Kết quả phân bố tần suất theo màu sắc sản phẩm phản ánh rõ sự đa dạng về thị hiếu người tiêu dùng, đồng thời giúp doanh nghiệp xác định những tông màu được ưa chuộng nhất.

Trong số 25 màu được liệt kê, Yellow (4.46%), Silver (4.44%), Olive (4.54%), và Teal (4.41%) là những màu nổi bật, có mức tiêu thụ cao nhất. Điều này cho thấy người tiêu dùng đang có xu hướng quan tâm đến những sắc thái tươi sáng hoặc độc đáo, phản ánh tính cá nhân hóa cao trong lựa chọn sản phẩm.

Ngược lại, các màu như Gold (3.54%), Brown (3.62%), và White (3.64%) có tỷ lệ thấp hơn, cho thấy sức hút tương đối hạn chế. Dù vậy, nhóm màu trung tính như Black (4.28%), Gray (4.08%), và Beige (3.77%) vẫn giữ được vị trí ổn định, thể hiện sự ưa chuộng tính linh hoạt và dễ phối đồ.

7.Thống kê mô tả biến Season

Thống kê Tần suất

# Tính tần số và tần suất
season_freq <- table(b$Season)
season_prop <- table(b$Season) / sum(nrow(b)) 
print(season_freq)
## 
##   Fall Spring Summer Winter 
##    975    999    955    971
# Tạo dataframe cho bảng
table_data7 <- data.frame(
  `Mùa` = names(season_freq),
  `Tần số` = as.numeric(season_freq),
  `Tần suất (%)` = round(season_prop * 100, 2)
)
colnames(table_data7) <- c("Mùa", "Tần số", "Mùa", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data7, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Mùa Tần số Mùa Tần suất (%)
Fall 975 Fall 25.00
Spring 999 Spring 25.62
Summer 955 Summer 24.49
Winter 971 Winter 24.90

Trực quan hóa

# Tạo bảng màu (cố định cho 4 mùa)
num_seasons <- length(season_freq)
colors <- c("#0066CC", "#00CC99", "#FF6666", "#FFCC00")[1:num_seasons]  # ✅ Sửa đúng cách trích màu

# Tạo biểu đồ cột
bar_positions7 <- barplot(season_freq, 
                          main = "Phân phối khách hàng theo mùa",
                          xlab = "Mùa",
                          ylab = "Số lượng giao dịch",
                          col = colors,  
                          names.arg = names(season_freq),  
                          las = 1,  
                          cex.names = 1,  
                          ylim = c(0, max(season_freq, na.rm = TRUE) * 1.2))

# Thêm nhãn số trên mỗi cột
text(x = bar_positions7, 
     y = season_freq + max(season_freq, na.rm = TRUE) * 0.05,  
     labels = season_freq,  
     pos = 3,  
     col = "black",  
     cex = 0.9)

Kết quả phân phối tần suất mua sắm theo mùa cho thấy sự phân bổ khá đồng đều trong hành vi tiêu dùng của khách hàng trong suốt cả năm. Cụ thể, mùa Xuân chiếm tỷ trọng cao nhất với 25.62% tổng số lượt mua, tiếp đến là mùa Thu (25.00%), mùa Đông (24.90%) và mùa Hè (24.49%). Sự chênh lệch không đáng kể giữa các mùa phản ánh tính ổn định trong nhu cầu mua sắm của người tiêu dùng, cho thấy hoạt động mua sắm không chịu tác động mạnh bởi yếu tố thời vụ. Tuy nhiên, sự nhỉnh hơn nhẹ của mùa Xuân có thể liên quan đến nhu cầu làm mới trang phục và chuẩn bị cho các dịp lễ hội đầu năm.

8.Thống kê mô tả biến Subscription Status

Thống kê Tần suất

# Tính tần số và tần suất
subscriptionstatus_freq <- table(b$Subscription.Status)
subscriptionstatus_prop <- table(b$Subscription.Status) / sum(nrow(b)) 
print(subscriptionstatus_freq)
## 
##   No  Yes 
## 2843 1057
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo dataframe cho bảng
table_data8 <- data.frame(
  `Trạng thái đăng ký` = names(subscriptionstatus_freq),
  `Tần số` = as.numeric(subscriptionstatus_freq),
  `Tần suất (%)` = round(subscriptionstatus_prop * 100, 2))

colnames(table_data8) <- c("Trạng thái đăng ký", "Tần số", "Trạng thái đăng ký", "Tần suất(%)")



# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data8, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Trạng thái đăng ký Tần số Trạng thái đăng ký Tần suất(%)
No 2843 No 72.9
Yes 1057 Yes 27.1

Trực quan hóa

# Tạo biểu đồ cột
bar_positions8 <- barplot(subscriptionstatus_freq, 
                         main = "Phân phối khách hàng theo trạng thái đăng ký",
                          xlab = "Trạng thái đăng ký",
                          ylab = "Số lượng giao dịch",
                         col = c("#FF99CC", "#00CC99"),  
                         las = 1,  # nhãn trục x để ngang
                         cex.names = 0.8,  # Giảm kích thước chữ nhãn trục x
                         ylim = c(0, max(subscriptionstatus_freq) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions8, 
     y = subscriptionstatus_freq + 200,  # Tăng khoảng cách nhãn lên 200 để hiển thị rõ
     labels = subscriptionstatus_freq,  # Giá trị tần suất
     pos = 3,  # Đặt nhãn phía trên cột
     col = "black",  # Màu chữ đen
     cex = 0.9)  # Kích thước chữ

Phân tích tần suất đăng ký cho thấy phần lớn khách hàng chưa đăng ký tài khoản hoặc chương trình thành viên của doanh nghiệp. Cụ thể, 72.9% người tiêu dùng thuộc nhóm “Không đăng ký”, trong khi chỉ có 27.1% đã thực hiện đăng ký. Sự chênh lệch đáng kể này phản ánh một tiềm năng lớn cho việc mở rộng tệp khách hàng thân thiết thông qua các chiến lược khuyến khích đăng ký hiệu quả hơn. Việc người tiêu dùng chưa sẵn sàng đăng ký có thể xuất phát từ các nguyên nhân như quy trình đăng ký phức tạp, thiếu lợi ích rõ ràng, hoặc lo ngại về quyền riêng tư. Do đó, doanh nghiệp cần rà soát lại trải nghiệm người dùng, đồng thời thiết kế lại các chính sách ưu đãi dành riêng cho người đăng ký để gia tăng tỷ lệ chuyển đổi và phát triển mối quan hệ lâu dài với khách hàng.

9.Thống kê mô tả biến Discount Applied

Thống kê Tần suất

# Tính tần số và tần suất
discountapplied_freq <- table(b$Discount.Applied)
discountapplied_prop <- table(b$Discount.Applied) / sum(nrow(b)) 
print(discountapplied_freq)
## 
##   No  Yes 
## 2223 1677
# Tạo dataframe cho bảng
table_data9 <- data.frame(
  `Trạng thái giảm giá` = names(discountapplied_freq),
  `Tần số` = as.numeric(discountapplied_freq),
  `Tần suất (%)` = round(discountapplied_prop * 100, 2)
)
colnames(table_data9) <- c("Trạng thái giảm giá", "Tần số","Trạng thái giảm giá", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data9, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Trạng thái giảm giá Tần số Trạng thái giảm giá Tần suất (%)
No 2223 No 57
Yes 1677 Yes 43

Trực quan hóa

num_discounts <- length(discountapplied_freq)
colors <- c("#FF99CC", "#00CC99")[1:num_discounts]  # Chọn màu đủ

# Tạo biểu đồ cột
bar_positions9 <- barplot(discountapplied_freq, 
                        main = "Phân phối khách hàng theo trạng thái giảm giá",
                          xlab = "Trạng thái giảm giá",
                          ylab = "Số lượng giao dịch",
                         col = colors,  # Sử dụng bảng màu cố định
                          names.arg = names(discountapplied_freq),  # Tên trạng thái
                          las = 1,  # Nhãn trục x nằm ngang (ít giá trị)
                          cex.names = 1,  # Kích thước nhãn trục x rõ ràng
                          ylim = c(0, max(discountapplied_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions9, 
     y = discountapplied_freq + max(discountapplied_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = discountapplied_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.9)  # Kích thước chữ

Kết quả thống kê về trạng thái giảm giá cho thấy rằng có 57% giao dịch không đi kèm với chương trình giảm giá, trong khi 43% còn lại có áp dụng hình thức khuyến mãi. Tỷ lệ tương đối cao của các giao dịch có giảm giá phản ánh vai trò quan trọng của các chương trình ưu đãi trong chiến lược kích cầu tiêu dùng. Tuy nhiên, việc hơn một nửa số giao dịch không cần đến giảm giá để hoàn tất cho thấy vẫn tồn tại một nhóm khách hàng sẵn sàng chi trả theo mức giá gốc. Điều này mở ra cơ hội cho doanh nghiệp tối ưu hóa chính sách định giá, kết hợp hài hòa giữa giá trị sản phẩm và kỳ vọng của khách hàng, từ đó nâng cao doanh thu mà vẫn đảm bảo khả năng cạnh tranh.

10.Thống kê mô tả biến Promo Code Used

Thống kê Tần suất

# Tính tần số và tần suất
promocodeused_freq <- table(b$Promo.Code.Used)
promocodeused_prop <- table(b$Promo.Code.Used) / sum(nrow(b)) 
print(promocodeused_freq)
## 
##   No  Yes 
## 2223 1677
# Tạo dataframe cho bảng
table_data10 <- data.frame(
  `Trạng thái sử dụng mã khuyến mãi` = names(promocodeused_freq),
  `Tần số` = as.numeric(promocodeused_freq),
  `Tần suất (%)` = round(promocodeused_prop * 100, 2)
)
colnames(table_data10) <- c("Trạng thái sử dụng mã khuyến mãi", "Tần số", "Trạng thái sử dụng mã khuyến mãi ", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data10, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Trạng thái sử dụng mã khuyến mãi Tần số Trạng thái sử dụng mã khuyến mãi Tần suất (%)
No 2223 No 57
Yes 1677 Yes 43

Trực quan hóa

# Tạo biểu đồ cột
bar_positions10 <- barplot(promocodeused_freq, 
                           main = "Phân phối khách hàng theo trạng thái sử dụng mã khuyến mãi",
                           xlab = "Trạng thái sử dụng mã khuyến mãi",
                           ylab = "Số lượng giao dịch",
                           col = colors,  # Sử dụng bảng màu cố định
                           names.arg = names(promocodeused_freq),  # Tên trạng thái
                           las = 1,  # Nhãn trục x nằm ngang (ít giá trị)
                           cex.names = 1,  # Kích thước nhãn trục x rõ ràng
                           ylim = c(0, max(promocodeused_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions10, 
     y = promocodeused_freq + max(promocodeused_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = promocodeused_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.9)  # Kích thước chữ

Phân tích trạng thái sử dụng mã khuyến mãi cho thấy 43% các giao dịch có áp dụng mã giảm giá, trong khi 57% không sử dụng mã khuyến mãi. Tỷ lệ sử dụng mã khuyến mãi khá cao, cho thấy mã giảm giá là một công cụ quan trọng thúc đẩy hành vi mua sắm của khách hàng. Việc gần một nửa số giao dịch tận dụng mã khuyến mãi chứng tỏ hiệu quả của các chương trình tiếp thị trong việc thu hút và giữ chân khách hàng. Tuy nhiên, tỷ lệ 57% không sử dụng mã cũng cho thấy vẫn có nhóm khách hàng không phụ thuộc vào ưu đãi, điều này giúp doanh nghiệp cân bằng giữa chính sách khuyến mãi và duy trì giá trị sản phẩm trên thị trường.

11.Thống kê mô tả biến Payment Method

Thống kê Tần suất

# Tính tần số và tần suất
paymentmethod_freq <- table(b$Payment.Method)
paymentmethod_prop <- table(b$Payment.Method) / sum(nrow(b)) 
print(paymentmethod_freq)
## 
## Bank Transfer          Cash   Credit Card    Debit Card        PayPal 
##           612           670           671           636           677 
##         Venmo 
##           634
# Tạo dataframe cho bảng
table_data11 <- data.frame(
  `Phương thức thanh toán` = names(paymentmethod_freq),
  `Tần số` = as.numeric(paymentmethod_freq),
  `Tần suất (%)` = round(paymentmethod_prop * 100, 2)
)
colnames(table_data11) <- c("Phương thức thanh toán", "Tần số", "Phương thức thanh toán", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data11, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Phương thức thanh toán Tần số Phương thức thanh toán Tần suất (%)
Bank Transfer 612 Bank Transfer 15.69
Cash 670 Cash 17.18
Credit Card 671 Credit Card 17.21
Debit Card 636 Debit Card 16.31
PayPal 677 PayPal 17.36
Venmo 634 Venmo 16.26

Trực quan hóa

# Tạo bảng màu (đủ cho số phương thức)
num_methods <- length(paymentmethod_freq)
colors <- c("#0066CC", "#00CC99", "#FF6666", "#FFCC00", "#9933CC", "#33CCCC")[1:num_methods]  # Chọn màu đủ

# Tạo biểu đồ cột
bar_positions11 <- barplot(paymentmethod_freq, 
                           main = "Phân phối khách hàng theo phương thức thanh toán",
                           xlab = "Phương thức thanh toán",
                           ylab = "Số lượng giao dịch",
                           col = colors,  # Sử dụng bảng màu cố định
                           names.arg = names(paymentmethod_freq),  # Tên phương thức
                           las = 1,  # Xoay nhãn trục x để ngang
                           cex.names = 0.8,  # Giảm kích thước nhãn trục x
                           ylim = c(0, max(paymentmethod_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions11, 
     y = paymentmethod_freq + max(paymentmethod_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = paymentmethod_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.9)  # Kích thước chữ

Phân tích dữ liệu phương thức thanh toán cho thấy sự phân bổ tương đối cân bằng giữa các hình thức sử dụng. Trong đó, PayPal chiếm tỷ lệ cao nhất với 17,36%, theo sát là thẻ tín dụng (Credit Card) và thanh toán tiền mặt (Cash) với tỷ lệ lần lượt là 17,21% và 17,18%. Các phương thức khác như chuyển khoản ngân hàng (Bank Transfer), thẻ ghi nợ (Debit Card) và Venmo cũng có tỷ lệ tương đối đồng đều, dao động từ 15,69% đến 16,31%. Kết quả này phản ánh xu hướng đa dạng hóa các hình thức thanh toán mà người tiêu dùng ưu tiên, đồng thời cho thấy nhu cầu về sự thuận tiện và linh hoạt trong quá trình giao dịch. Do đó, việc duy trì đa dạng các phương thức thanh toán là cần thiết để đáp ứng kỳ vọng của khách hàng cũng như nâng cao hiệu quả kinh doanh.

12.Thống kê mô tả biến Frequency of Purchases

Thống kê Tần suất

# Tính tần số và tần suất
frequencyofpurchases_freq <- table(b$Frequency.of.Purchases)
frequencyofpurchases_prop <- table(b$Frequency.of.Purchases) / sum(nrow(b)) 
print(frequencyofpurchases_freq)
## 
##       Annually      Bi-Weekly Every 3 Months    Fortnightly        Monthly 
##            572            547            584            542            553 
##      Quarterly         Weekly 
##            563            539
# Tạo dataframe cho bảng
table_data12 <- data.frame(
   `Tần suất mua hàng` = names(frequencyofpurchases_freq),
  `Tần số` = as.numeric(frequencyofpurchases_freq),
  `Tần suất (%)` = round(frequencyofpurchases_prop * 100, 2)
)

colnames(table_data12) <- c("Tần suất mua hàng", "Tần số", "Tần suất mua hàng ", "Tần suất (%)")
# Đặt mã hóa UTF-8 để hỗ trợ tiếng Việt
Sys.setlocale("LC_ALL", "en_US.UTF-8")
## [1] "LC_COLLATE=en_US.UTF-8;LC_CTYPE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8"
# Tạo bảng kẻ
library(knitr)
library(kableExtra)

kable(table_data12, format = "markdown", align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Tần suất mua hàng Tần số Tần suất mua hàng Tần suất (%)
Annually 572 Annually 14.67
Bi-Weekly 547 Bi-Weekly 14.03
Every 3 Months 584 Every 3 Months 14.97
Fortnightly 542 Fortnightly 13.90
Monthly 553 Monthly 14.18
Quarterly 563 Quarterly 14.44
Weekly 539 Weekly 13.82

Trực quan hóa

num_frequencies <- length(frequencyofpurchases_freq)
colors <- c("#0066CC", "#00CC99", "#FF6666", "#FFCC00", "#9933CC", "#33CCCC", "#CC3366")[1:num_frequencies]  # Chọn màu đủ

# Tạo biểu đồ cột
bar_positions12 <- barplot(frequencyofpurchases_freq, 
                           main = "Phân phối khách hàng theo tần suất mua hàng",
                           xlab = "Tần suất mua hàng",
                           ylab = "Số lượng giao dịch",
                           col = colors,  # Sử dụng bảng màu cố định
                           names.arg = names(frequencyofpurchases_freq),  # Tên tần suất
                           las = 2,  # Xoay nhãn trục x 90 độ để dễ đọc
                           cex.names = 0.8,  # Giảm kích thước nhãn trục x
                           ylim = c(0, max(frequencyofpurchases_freq, na.rm = TRUE) * 1.2))  # Mở rộng trục y lên 120%

# Thêm nhãn số trên mỗi cột
text(x = bar_positions12, 
     y = frequencyofpurchases_freq + max(frequencyofpurchases_freq, na.rm = TRUE) * 0.05,  # Khoảng cách nhãn động
     labels = frequencyofpurchases_freq,  # Giá trị tần số
     pos = 3,  # Đặt nhãn trên cột
     col = "black",  # Màu chữ
     cex = 0.9)  # Kích thước chữ

Kết quả cho thấy sự phân bổ tương đối đồng đều giữa các khoảng thời gian khác nhau. Trong đó, nhóm khách hàng mua hàng theo chu kỳ mỗi ba tháng (Every 3 Months) chiếm tỷ lệ cao nhất với 14,97%, tiếp theo là nhóm mua hàng hàng quý (Quarterly) với 14,44%, và mua hàng hàng năm (Annually) chiếm 14,67%. Các nhóm còn lại như mua hàng hàng tháng (Monthly), hai tuần một lần (Bi-Weekly), hàng tuần (Weekly) và mỗi hai tuần (Fortnightly) cũng dao động quanh mức 13,8% đến 14,2%. Kết quả này phản ánh đa dạng về thói quen mua sắm của khách hàng, cho thấy nhu cầu và tần suất tiêu dùng có sự phân hóa nhẹ,

Phần 3:Ước lượng Khoảng và Kiểm định Giả thuyết cho Tỷ lệ (Một biến)

Lý thuyết

Ước lượng khoảng tin cậy cho tỷ lệ mẫu

Trong thống kê suy diễn, chúng ta thường cần ước lượng một tham số tổng thểdựa trên dữ liệu mẫu. Đối với tỷ lệ, khoảng tin cậy (confidence interval – CI) được xác định bằng cách sử dụng tỷ lệ mẫu \(\hat{p}\), độ lệch chuẩn và phân phối chuẩn chuẩn hóa.

$$ Tỷ lệ mẫu được tính bằng:

\[ \hat{p} = \frac{x}{n} \]

Khoảng tin cậy 95% cho tỷ lệ:

\[ CI = \hat{p} \pm z_{\alpha/2} \cdot \sqrt{ \frac{ \hat{p}(1 - \hat{p}) }{n} } \]

Trong đó:

  • \(\hat{p}\): tỷ lệ mẫu

  • \(z_{\alpha/2} \approx 1.96\): giá trị tới hạn từ phân phối chuẩn chuẩn hóa với mức tin cậy 95%

  • \(n\): kích thước mẫu

Kiểm định giả thuyết cho một tỷ lệ

Giả sử ta muốn kiểm tra xem tỷ lệ mẫu có khác một giá trị giả định \(p_0\) hay không. Khi đó, kiểm định giả thuyết được đặt như sau:

Giả thuyết kiểm định:

\[ H_0: p = p_0 \quad \text{vs} \quad H_1: p \neq p_0 \]

Thống kê kiểm định:

\[ z = \frac{ \hat{p} - p_0 }{ \sqrt{ \frac{ p_0 (1 - p_0) }{n} } } \]

Cách tính p-value (kiểm định hai phía):

\[ p\text{-value} = 2 \cdot (1 - \Phi(|z|)) \] $$

1.Hạng mục Female của biến Gender

Ước lượng Khoảng Tin cậy

x <- table(b$Gender)[["Female"]]
n <- sum(table(b$Gender))
CI<- prop.test(x,n,conf.level = 0.95,correct = TRUE)
cat("Tỷ lệ mẫu ước lượng \n \n",
    CI[["estimate"]],"\n \n",
    "Khoảng ước lượng 95%  \n \n",CI[["conf.int"]])
## Tỷ lệ mẫu ước lượng 
##  
##  0.32 
##  
##  Khoảng ước lượng 95%  
##  
##  0.3054166 0.3349408

Kết quả phân tích cho thấy với mức độ tin cậy 95%, tỷ lệ khách hàng nữ trong tổng thể được ước lượng nằm trong khoảng từ 30.54% đến 33.49%. Điều này cung cấp một phạm vi hợp lý phản ánh tỷ lệ nữ giới tham gia giao dịch trong mẫu nghiên cứu.

Kiểm định giả thuyết

CI<- prop.test(x,n,conf.level = 0.95,p = 0.5 ,correct = TRUE)
CI
## 
##  1-sample proportions test with continuity correction
## 
## data:  x out of n, null probability 0.5
## X-squared = 504.72, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.3054166 0.3349408
## sample estimates:
##    p 
## 0.32

Đặt giả thuyết:

H₀: Tỷ lệ khách hàng nữ trong tổng thể là 0.5 (tức 50%).

H₁: Tỷ lệ khách hàng nữ trong tổng thể khác 0.5.

Vì p-value = 4.695e-10 < 0.05, nên chúng ta bác bỏ giả thuyết H₀ tại mức ý nghĩa 5%. Vậy Tỷ lệ khách hàng nữ trong tổng thể khác 0.5

2.Hạng mục Fall của biến Season

Ước lượng Khoảng Tin cậy

# Trích xuất số lượng "Fall" và tổng số giao dịch
x<- table(b$Season)[["Fall"]]
n <- sum(table(b$Season))
CI <- prop.test(x,n,conf.level = 0.95,correct = TRUE)
cat("Tỷ lệ mẫu ước lượng \n \n",
    CI[["estimate"]],"\n \n",
    "Khoảng ước lượng 95%  \n \n",CI[["conf.int"]])
## Tỷ lệ mẫu ước lượng 
##  
##  0.25 
##  
##  Khoảng ước lượng 95%  
##  
##  0.2365348 0.2639618

Với độ tin cậy 95%, tỷ lệ giao dịch diễn ra trong mùa Thu (Fall) được ước tính nằm trong khoảng từ 23.65% đến 26.39%. Khoảng tin cậy này phản ánh sự ổn định và mức độ phổ biến của mùa Thu trong tổng số giao dịch.

Kiểm định giả thuyết

CI<- prop.test(x,n,conf.level = 0.95,p = 1/4 ,correct = TRUE)
CI
## 
##  1-sample proportions test without continuity correction
## 
## data:  x out of n, null probability 1/4
## X-squared = 0, df = 1, p-value = 1
## alternative hypothesis: true p is not equal to 0.25
## 95 percent confidence interval:
##  0.2366606 0.2638314
## sample estimates:
##    p 
## 0.25

Đặt giả thuyết:

H₀: Tỷ lệ khách hàng thực hiện giao dịch trong mùa thu trong tổng thể p=0.25

H₁: Tỷ lệ khách hàng thực hiện giao dịch trong mùa thu trong tổng thể p khác 0.25

Với mức ý nghĩa 5%, vì p-value = 1 > 0.05, ta không đủ bằng chứng để bác bỏ giả thuyết không ( H₀).Nói cách khác, tỷ lệ mẫu quan sát được là 25% hoàn toàn phù hợp với giả định ban đầu.

3.Hạng mục M của biến Size

Ước lượng Khoảng Tin cậy

# Trích xuất số lượng "M" và tổng số giao dịch
x <- table(b$Size)[["M"]]
n <- sum(table(b$Size))
CI <- prop.test(x,n,conf.level = 0.95,correct = TRUE)
cat("Tỷ lệ mẫu ước lượng \n \n",
    CI[["estimate"]],"\n \n",
    "Khoảng ước lượng 95%  \n \n",CI[["conf.int"]])
## Tỷ lệ mẫu ước lượng 
##  
##  0.45 
##  
##  Khoảng ước lượng 95%  
##  
##  0.4343155 0.4657837

Khoảng tin cậy [ 0.4343155, 0.4657837]. Điều này có nghĩa là: Với độ tin cậy 95%, ta ước lượng rằng tỷ lệ giao dịch thuộc nhóm “M” trong tổng thể nằm trong khoảng từ 43.43% đến 46.58%

Kiểm định giả thuyết

CI<- prop.test(x,n,conf.level = 0.95,p = 1/2 ,correct = TRUE,alternative = "less")
CI
## 
##  1-sample proportions test with continuity correction
## 
## data:  x out of n, null probability 1/2
## X-squared = 38.8, df = 1, p-value = 2.347e-10
## alternative hypothesis: true p is less than 0.5
## 95 percent confidence interval:
##  0.000000 0.463262
## sample estimates:
##    p 
## 0.45

Đặt giả thuyết:

Giả thuyết H₀: Tỷ lệ của giao dịch có kích cỡ “M” là 0.5 (50%).

Giả thuyết H₁: Tỷ lệ của giao dịch có kích cỡ “M” khác 0.5

Với mức ý nghĩa 5%, vì p-value = 2.347e-10 < 0.05, ta bác bỏ giả thuyết H₀. Nói cách khác, Tỷ lệ của giao dịch có kích cỡ “M” khác 0.5.

Phần 4: Phân tích Mối quan hệ giữa Hai biến Định tính (Bivariate Analysis)

Kiểm định thống kê: Kiểm định Chi-bình phương

Trong thống kê, kiểm định Chi-bình phương độc lập (Chi-square test of independence) được sử dụng để kiểm tra xem hai biến phân loại có độc lập với nhau hay không. Dữ liệu thường được trình bày dưới dạng bảng chéo (contingency table).

Giả thuyết kiểm định

\(H_0\): Hai biến là độc lập (không có mối quan hệ).

\(H_1\): Hai biến không độc lập (có mối quan hệ).

Công thức thống kê kiểm định

Giá trị thống kê Chi-bình phương được tính theo công thức: \[ \chi^2 = \sum \frac{(O_i - E_i)^2}{E_i} \]

Trong đó:

\(O_{ij}\): Tần số quan sát tại ô thứ \((i, j)\).

\(E_{ij}\): Tần số kỳ vọng tại ô thứ \((i, j)\), được tính bằng:

Tần suất kỳ vọng \(E_{ij}\) được tính theo công thức:

\[ E_{ij} = \frac{(Tổng \text{ hàng}_i) \times (Tổng \text{ cột}_j)}{Tổng \text{ số quan sát}} \]

1. Cặp biến: Gender và Category

Bảng tần suất chéo

# Tạo bảng tần suất chéo cho Gender và Category
contingency_table <- table(b$Gender, b$Category)
cat("\nBảng tần suất chéo cho Gender và Category:\n")
## 
## Bảng tần suất chéo cho Gender và Category:
print(contingency_table)
##         
##          Accessories Clothing Footwear Outerwear
##   Female         392      556      199       101
##   Male           848     1181      400       223
# Tính tỷ lệ phần trăm theo hàng
contingency_table_prop <- prop.table(contingency_table, margin = 1) * 100
cat("\nTỷ lệ phần trăm theo hàng cho Gender và Category:\n")
## 
## Tỷ lệ phần trăm theo hàng cho Gender và Category:
print(round(contingency_table_prop, 1))
##         
##          Accessories Clothing Footwear Outerwear
##   Female        31.4     44.6     15.9       8.1
##   Male          32.0     44.5     15.1       8.4

Trực quan hóa

library(ggplot2)
library(dplyr)
library(scales)

# Chuyển sang data frame
df_prop <- as.data.frame(contingency_table_prop)
colnames(df_prop) <- c("Gender", "Category", "Percentage")

# Vẽ biểu đồ cột nhóm
ggplot(df_prop, aes(x = Gender, y = Percentage, fill = Category)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = paste0(round(Percentage, 1), "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5,
            size = 3.8,
            color = "black") +
  scale_fill_brewer(palette = "Pastel2") +
  labs(
    title = "Tỷ lệ phần trăm Loại sản phẩm theo Giới tính",
    x = "Giới tính",
    y = "Tỷ lệ (%)",
    fill = "Loại sản phẩm"
  ) +
  scale_y_continuous(labels = label_percent(scale = 1)) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
    legend.position = "top",
    axis.text.x = element_text(angle = 0, vjust = 0.5),
    panel.grid.major.x = element_blank()
  )

Kết quả phân tích bảng cho thấy sự phân bổ tương đối đồng đều giữa nam và nữ trong việc lựa chọn các loại sản phẩm, phản ánh thị hiếu tiêu dùng khá tương đồng giữa hai giới trong mẫu khảo sát. Cụ thể, tỷ lệ lựa chọn sản phẩm Clothing chiếm tỷ trọng cao nhất ở cả hai nhóm giới tính, với 44.6% ở nữ và 44.5% ở nam, cho thấy đây là danh mục được ưa chuộng nhất. Đối với sản phẩm Accessories, tỷ lệ lựa chọn giữa hai giới cũng gần như tương đương (31.4% ở nữ và 32.0% ở nam), phản ánh xu hướng tiêu dùng tương đối cân bằng.

Tuy nhiên, có sự khác biệt nhẹ trong nhóm sản phẩm Footwear, khi nữ giới có tỷ lệ lựa chọn cao hơn một chút (15.9%) so với nam (15.1%), trong khi đối với nhóm Outerwear, nam giới có xu hướng tiêu dùng cao hơn nữ giới với tỷ lệ 8.4% so với 8.1%.

Kiểm định Thống kê (Kiểm định Chi-bình phương)

Để xác định xem mối quan hệ giữa Gender và Category có ý nghĩa thống kê hay không, cần thực hiện thêm kiểm định (như kiểm định Chi-bình phương).

# Thực hiện kiểm định Chi-bình phương
chi_test <- chisq.test(contingency_table)

# Báo cáo kết quả
cat("Giá trị Chi-bình phương:", chi_test$statistic, "\n")
## Giá trị Chi-bình phương: 0.5984208
cat("Bậc tự do (df):", chi_test$parameter, "\n")
## Bậc tự do (df): 3
cat("Giá trị p:", chi_test$p.value, "\n")
## Giá trị p: 0.8967938

Giả thuyết H₀: Hai biến Gender và Category độc lập với nhau, tức là không có mối liên hệ.

Giả thuyết H₁: Hai biến Gender và Category có liên quan với nhau, tức là có mối liên hệ.

Vì p-value =0.8967938 > 0.05, nên chưa đủ cơ sở để bác bỏ giả thuyết H₀ ở mức ý nghĩa 5%. Nghĩa là không có bằng chứng thống kê đủ mạnh để khẳng định rằng giới tính và loại sản phẩm có mối quan hệ phụ thuộc lẫn nhau. Nói cách khác, sự phân bố tỷ lệ các loại sản phẩm trong mẫu khảo sát là tương đối giống nhau giữa nam và nữ, điều này cũng phù hợp với quan sát từ bảng phân phối tỷ lệ phần trăm theo hàng đã trình bày trước đó.

Về mặt thực tiễn, điều này hàm ý rằng giới tính không phải là yếu tố ảnh hưởng đáng kể đến sự khác biệt trong lựa chọn danh mục sản phẩm trong mẫu dữ liệu nghiên cứu

2. Cặp biến: Gender và Frequency of Purchases

Bảng tần suất chéo

# Tạo bảng tần suất chéo cho Gender và Frequency.of.Purchases
contingency_table <- table(b$Gender, b$Frequency.of.Purchases)
cat("\nBảng tần suất chéo cho Gender và Frequency.of.Purchases:\n")
## 
## Bảng tần suất chéo cho Gender và Frequency.of.Purchases:
print(contingency_table)
##         
##          Annually Bi-Weekly Every 3 Months Fortnightly Monthly Quarterly Weekly
##   Female      185       188            186         163     185       169    172
##   Male        387       359            398         379     368       394    367
# Tính tỷ lệ phần trăm theo hàng
contingency_table_prop <- prop.table(contingency_table, margin = 1) * 100
cat("\nTỷ lệ phần trăm theo hàng cho Gender và Frequency.of.Purchases:\n")
## 
## Tỷ lệ phần trăm theo hàng cho Gender và Frequency.of.Purchases:
print(round(contingency_table_prop, 1))
##         
##          Annually Bi-Weekly Every 3 Months Fortnightly Monthly Quarterly Weekly
##   Female     14.8      15.1           14.9        13.1    14.8      13.5   13.8
##   Male       14.6      13.5           15.0        14.3    13.9      14.9   13.8

Trực quan hóa

library(ggplot2)
library(dplyr)
library(scales)

# Chuyển bảng tỷ lệ thành data frame
df_prop <- as.data.frame(contingency_table_prop)
colnames(df_prop) <- c("Gender", "Frequency", "Percentage")

# Vẽ biểu đồ cột nhóm
ggplot(df_prop, aes(x = Gender, y = Percentage, fill = Frequency)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = paste0(round(Percentage, 1), "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5,
            size = 3.8,
            color = "black") +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Tỷ lệ phần trăm Tần suất mua hàng theo Giới tính",
    x = "Giới tính",
    y = "Tỷ lệ (%)",
    fill = "Tần suất mua hàng"
  ) +
  scale_y_continuous(labels = label_percent(scale = 1)) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
    legend.position = "top",
    axis.text.x = element_text(angle = 0, vjust = 0.5),
    panel.grid.major.x = element_blank()
  )

Phân tích cho thấy sự phân bố tần suất mua hàng giữa nam và nữ là tương đối đồng đều, không có sự sai khác rõ rệt nào về mặt tỷ lệ phần trăm giữa các nhóm tần suất. Cụ thể, đối với nhóm Weekly, cả nam và nữ đều có cùng tỷ lệ 13.8%, cho thấy mức độ tương đồng tuyệt đối về thói quen mua hàng hàng tuần giữa hai giới.

Ở các nhóm tần suất khác, sự khác biệt giữa tỷ lệ phần trăm của nam và nữ nhìn chung không đáng kể. Ví dụ, trong nhóm Bi-Weekly, nữ giới chiếm 15.1%, cao hơn một chút so với nam (13.5%), trong khi ở nhóm Fortnightly, nam giới lại cao hơn (14.3%) so với nữ (13.1%). Những sự chênh lệch nhỏ này có thể phản ánh sự dao động ngẫu nhiên trong hành vi mua sắm cá nhân, hơn là một xu hướng có tính hệ thống.

Một điểm đáng chú ý là ở nhóm Quarterly, nam giới có tỷ lệ 14.9%, cao hơn nữ (13.5%), nhưng khoảng cách vẫn không đủ lớn để đưa ra kết luận có ý nghĩa thống kê nếu không được hỗ trợ bởi một kiểm định chính thức.

Tổng thể, bảng phân phối tỷ lệ phần trăm này cho thấy tính nhất quán và tương đối cân bằng về hành vi tiêu dùng giữa hai giới trong mẫu khảo sát, phản ánh rằng giới tính có thể không phải là yếu tố phân biệt rõ rệt đối với tần suất mua hàng

Kiểm định Thống kê (Kiểm định Chi-bình phương)

# Thực hiện kiểm định Chi-bình phương
chi_test <- chisq.test(contingency_table)

# Báo cáo kết quả
cat("Giá trị Chi-bình phương:", chi_test$statistic, "\n")
## Giá trị Chi-bình phương: 3.928009
cat("Bậc tự do (df):", chi_test$parameter, "\n")
## Bậc tự do (df): 6
cat("Giá trị p:", chi_test$p.value, "\n")
## Giá trị p: 0.6864183

Giả thuyết H₀: Hai biến Gender và Frequency of Purchases độc lập với nhau, tức là không có mối liên hệ.

Giả thuyết H₁: Hai biến Gender và Frequency of Purchases có liên quan với nhau, tức là có mối liên hệ.

Vì p-value = 0.6864183 > 0.05, ta chưa đủ bằng chứng để bác bỏ giả thuyết không (H₀) tại mức ý nghĩa 5%. Nói cách khác, chưa có bằng chứng thống kê đủ mạnh để khẳng định rằng có mối quan hệ phụ thuộc giữa giới tính và tần suất mua hàng trong dữ liệu khảo sát.

Kết quả này hoàn toàn phù hợp với bảng tỷ lệ phần trăm theo hàng đã được trình bày trước đó, khi tỷ lệ các mức tần suất mua hàng giữa nam và nữ gần như đồng đều, không có sự sai khác đáng kể. Về mặt thực tiễn, điều này gợi ý rằng giới tính không phải là một yếu tố ảnh hưởng rõ rệt đến hành vi tiêu dùng xét theo khía cạnh tần suất mua sắm.

Từ góc độ nghiên cứu thị trường, các nhà quản lý hoặc nhà tiếp thị có thể cân nhắc rằng việc phân khúc khách hàng theo giới tính có thể không mang lại giá trị gia tăng đáng kể trong việc dự báo hay điều chỉnh các chiến lược theo tần suất tiêu dùng – ít nhất là trong bối cảnh và tập dữ liệu hiện tại.

3. Cặp biến: Category và Season:

Bảng tần suất chéo

# Tạo bảng tần suất chéo cho Category và Season
contingency_table <- table(b$Category, b$Season)
cat("\nBảng tần suất chéo cho Category và Season:\n")
## 
## Bảng tần suất chéo cho Category và Season:
print(contingency_table)
##              
##               Fall Spring Summer Winter
##   Accessories  324    301    312    303
##   Clothing     427    454    408    448
##   Footwear     136    163    160    140
##   Outerwear     88     81     75     80
# Tính tỷ lệ phần trăm theo hàng
contingency_table_prop <- prop.table(contingency_table, margin = 1) * 100
cat("\nTỷ lệ phần trăm theo hàng cho Category và Season:\n")
## 
## Tỷ lệ phần trăm theo hàng cho Category và Season:
print(round(contingency_table_prop, 1))
##              
##               Fall Spring Summer Winter
##   Accessories 26.1   24.3   25.2   24.4
##   Clothing    24.6   26.1   23.5   25.8
##   Footwear    22.7   27.2   26.7   23.4
##   Outerwear   27.2   25.0   23.1   24.7

Trực quan hóa

library(ggplot2)
library(dplyr)
library(scales)

# Chuyển sang data frame
df_prop <- as.data.frame(contingency_table_prop)
colnames(df_prop) <- c("Category", "Season", "Percentage")

# Vẽ biểu đồ cột nhóm
ggplot(df_prop, aes(x = Category, y = Percentage, fill = Season)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = paste0(round(Percentage, 1), "%")),
            position = position_dodge(width = 0.8),
            vjust = -0.5,
            size = 3.5,
            color = "black") +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Tỷ lệ phần trăm Mùa theo Loại sản phẩm",
    x = "Loại sản phẩm",
    y = "Tỷ lệ (%)",
    fill = "Mùa"
  ) +
  scale_y_continuous(labels = label_percent(scale = 1), limits = c(0, max(df_prop$Percentage) + 5)) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
    legend.position = "top",
    axis.text.x = element_text(angle = 30, hjust = 1),
    panel.grid.major.x = element_blank()
  )

Kết quả phản ánh sự phân bố lựa chọn sản phẩm theo mùa và loại hàng hóa, từ đó giúp làm sáng tỏ những xu hướng tiêu dùng mang tính thời vụ trong mẫu khảo sát. Tuy nhiên, một điểm đáng chú ý là sự phân bổ phần trăm trong từng loại sản phẩm theo các mùa không cho thấy sự khác biệt rõ rệt, mà thay vào đó là một mức dao động nhẹ, phản ánh sự tương đối đồng đều giữa các mùa trong mỗi danh mục.

Cụ thể, đối với nhóm Accessories, tỷ lệ lựa chọn dao động từ 24.3% (Spring) đến 26.1% (Fall) – một biên độ rất hẹp. Điều này cho thấy phụ kiện là mặt hàng ít chịu ảnh hưởng của tính thời vụ, có thể được tiêu dùng ổn định quanh năm. Tương tự, nhóm Clothing có sự phân bố gần như đồng đều, với tỷ lệ cao nhất vào mùa Spring (26.1%) và thấp nhất vào mùa Summer (23.5%), cho thấy nhu cầu quần áo là khá liên tục và thích ứng tốt với mọi mùa.

Đáng chú ý hơn là danh mục Footwear, với tỷ lệ cao nhất vào mùa Spring (27.2%) và Summer (26.7%), trong khi mùa Winter (23.4%) ghi nhận tỷ lệ thấp hơn, điều này có thể liên quan đến hành vi thay đổi giày dép linh hoạt hơn trong thời tiết ấm áp, trong khi vào mùa đông, việc mua sắm giày dép mới có thể bị hạn chế hơn do đặc thù thời tiết và nhu cầu ổn định.

Ngược lại, Outerwear – nhóm sản phẩm vốn có tính thời vụ cao – lại có tỷ lệ lựa chọn cao nhất vào mùa Fall (27.2%), phù hợp với giai đoạn chuyển mùa và nhu cầu tăng lên về áo khoác. Tuy nhiên, tỷ lệ không quá thấp ở các mùa còn lại cũng cho thấy có thể người tiêu dùng mua sắm áo khoác ngoài các mùa lạnh vì nhiều lý do khác nhau (chuẩn bị trước, khuyến mãi, du lịch…).

Tổng kết lại, bảng số liệu phản ánh rằng tính thời vụ trong tiêu dùng là có, nhưng không thực sự rõ rệt trong mẫu khảo sát này, ngoại trừ một số tín hiệu nhẹ từ nhóm Footwear và Outerwear. Để củng cố các kết luận mang tính khẳng định hơn, cần tiến hành kiểm định thống kê như Chi-bình phương, qua đó đánh giá xem liệu mối quan hệ giữa loại sản phẩm và mùa có ý nghĩa thống kê hay chỉ là dao động ngẫu nhiên.

Kiểm định Thống kê (Kiểm định Chi-bình phương)

# Thực hiện kiểm định Chi-bình phương
chi_test <- chisq.test(contingency_table)

# Báo cáo kết quả
cat("Giá trị Chi-bình phương:", chi_test$statistic, "\n")
## Giá trị Chi-bình phương: 7.933669
cat("Bậc tự do (df):", chi_test$parameter, "\n")
## Bậc tự do (df): 9
cat("Giá trị p:", chi_test$p.value, "\n")
## Giá trị p: 0.5408444

Giả thuyết H₀: Hai biến Category và Season độc lập với nhau, tức là không có mối liên hệ.

Giả thuyết H₁: Hai biến Category và Season có liên quan với nhau, tức là có mối liên hệ.

Vì p-value = 0.5408444 > 0.05, ta chưa có đủ bằng chứng để bác bỏ giả thuyết H₀.Điều này có nghĩa là không có bằng chứng thống kê đủ mạnh để kết luận rằng có mối quan hệ phụ thuộc giữa loại sản phẩm và mùa trong năm.

NKết quả này củng cố cho nhận định từ bảng tỷ lệ phần trăm theo hàng được trình bày trước đó, trong đó sự phân bố của từng loại sản phẩm theo mùa là khá đồng đều, với biên độ dao động không lớn. Điều này cho thấy rằng hành vi tiêu dùng các loại sản phẩm trong mẫu khảo sát là tương đối ổn định và ít chịu ảnh hưởng bởi yếu tố mùa vụ.

Về mặt thực tiễn, kết quả này gợi ý rằng các chiến lược phân phối và tiếp thị theo mùa đối với các danh mục sản phẩm như Clothing, Footwear, Accessories, Outerwear có thể không cần phải điều chỉnh quá mạnh mẽ theo mùa. Thay vào đó, các yếu tố khác như giá cả, khuyến mãi, xu hướng thời trang hoặc các dịp đặc biệt có thể đóng vai trò quan trọng hơn trong việc thúc đẩy nhu cầu theo thời gian.

Relative Risk

Tỷ số rủi ro (RR) là tỷ lệ giữa xác suất xảy ra sự kiện ở nhóm phơi nhiễm so với nhóm không phơi nhiễm. Nó thể hiện mức tăng (hoặc giảm) tương đối về nguy cơ.

Cách tính:

\[ RR = \frac{a / (a + b)}{c / (c + d)} \]

Ý nghĩa:

  • \(RR = 1\): Không có sự khác biệt nguy cơ giữa hai nhóm

  • \(RR > 1\): Nhóm A có nguy cơ cao hơn

  • \(RR < 1\): Nhóm A có nguy cơ thấp hơn

Rủi ro tương đối (Relative Risk/Risk Ratio) của biến Gender và Subscription Status

Tính Relative Risk (RR) giữa giới tính và trạng thái đăng ký, trong đó

  • Female là nhóm tham chiếu

  • Male là nhóm “phơi nhiễm” (exposed)

  • “Yes” là biến cố quan tâm (case – đã đăng ký)

# Tải thư viện
library(epitools)
# Tạo bảng chéo
cross_table <- table(b$Gender, b$Subscription.Status)

# Sắp xếp: Female là hàng đầu (exposed), Yes là cột thứ 2 (biến cố quan tâm)
cross_table <- cross_table[c("Female", "Male"), c("No", "Yes")]

# In bảng có tổng cộng
print(addmargins(cross_table))
##         
##            No  Yes  Sum
##   Female 1244    4 1248
##   Male   1599 1053 2652
##   Sum    2843 1057 3900
riskratio(cross_table)
## $data
##         
##            No  Yes Total
##   Female 1244    4  1248
##   Male   1599 1053  2652
##   Total  2843 1057  3900
## 
## $measure
##         risk ratio with 95% C.I.
##          estimate    lower    upper
##   Female   1.0000       NA       NA
##   Male   123.8824 46.51611 329.9252
## 
## $p.value
##         two-sided
##          midp.exact  fisher.exact  chi.square
##   Female         NA            NA          NA
##   Male            0 2.045619e-205 6.3672e-147
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Kết quả phân tích cho thấy sự khác biệt rất đáng kể về tỷ lệ xảy ra biến cố “Yes” giữa hai giới. Tỷ lệ nam giới phản ứng “Yes” đạt 39,7%, trong khi tỷ lệ này ở nữ giới chỉ là 0,32%. Tỷ số Risk Ratio = 123.8824 cho biết xác suất để khách hàng nam đăng kí thành viên cao gấp 123.8824 so với khách hàng nữ, với khoảng tin cậy 95% từ 46,52 đến 329,93, cho thấy mức chênh lệch là cực kỳ lớn và có ý nghĩa thống kê rõ rệt.

Với nhóm nữ được chọn làm nhóm tham chiếu (RR = 1), kết quả này đồng nghĩa với việc nam giới có nguy cơ xảy ra biến cố “Yes” cao hơn khoảng 124 lần so với nữ giới.

Tỷ lệ chênh (Odd Ratio)

Khái niệm

Odds (Tỷ lệ cược) của một sự kiện là tỉ số giữa xác suất sự kiện xảy ra với xác suất sự kiện không xảy ra.

Odd Ratio (Tỷ số chênh) là một thước đo được sử dụng phổ biến trong thống kê, đặc biệt là trong nghiên cứu dịch tễ học, để đánh giá mối liên hệ giữa phơi nhiễm và kết quả.

Cách tính:

\[ OR = \frac{a/b}{c/d} = \frac{a \cdot d}{b \cdot c} \]

Ý nghĩa:

  • \(OR = 1\): Không có sự khác biệt odds giữa hai nhóm

  • \(OR > 1\): Odds xảy ra sự kiện ở nhóm A cao hơn

  • \(OR < 1\): Odds ở nhóm A thấp hơn

Tính odds và oddsratio

# Tính odds của nhóm Female:
# Odds = số người đăng ký (Yes) / số người không đăng ký (No)
odd_F <- cross_table["Female", "Yes"] / cross_table["Female", "No"]

# Tính odds của nhóm Male:
odd_M <- cross_table["Male", "Yes"] / cross_table["Male", "No"]

# In odds của từng nhóm
cat("🎯 Odds nhóm Female:", odd_F, "\n")
## 🎯 Odds nhóm Female: 0.003215434
cat("🎯 Odds nhóm Male:", odd_M, "\n\n")
## 🎯 Odds nhóm Male: 0.6585366

Odds được hiểu là tỷ lệ giữa số người xảy ra biến cố (Yes) và số người không xảy ra biến cố (No). Từ kết quả trên:

Odds của nhóm nữ (Female) là 0.0032, nghĩa là trung bình cứ 1 người nữ xảy ra biến cố “Yes” thì có khoảng 311 người nữ không xảy ra biến cố.

Odds của nhóm nam (Male) là 0.6585, nghĩa là cứ 1 người nam xảy ra biến cố “Yes” thì có khoảng 1,52 người nam không xảy ra biến cố.

library(vcd)
library(DescTools)
# Cách 2: Dùng hàm OddsRatio() từ thư viện DescTools
or_result <- OddsRatio(cross_table)
cat("📌 Odds Ratio :", or_result, "\n")
## 📌 Odds Ratio : 204.8049

Tỷ số odds (Odds Ratio) giữa nam và nữ là khoảng 205, cho thấy rằng tỷ lệ nam giới đăng kí thành viên so với không đăng kí cao hơn 204.8049 lần so với tỷ lệ đó ở nữ

Đảo ngược lại

# Tải thư viện
library(epitools)
# Tạo bảng chéo
cross_table <- table(b$Gender, b$Subscription.Status)

cross_table <- cross_table[c("Male", "Female"), c("Yes", "No")]

# In bảng có tổng cộng
print(addmargins(cross_table))
##         
##           Yes   No  Sum
##   Male   1053 1599 2652
##   Female    4 1244 1248
##   Sum    1057 2843 3900
riskratio(cross_table)  
## $data
##         
##           Yes   No Total
##   Male   1053 1599  2652
##   Female    4 1244  1248
##   Total  1057 2843  3900
## 
## $measure
##         risk ratio with 95% C.I.
##          estimate    lower   upper
##   Male   1.000000       NA      NA
##   Female 1.653221 1.602685 1.70535
## 
## $p.value
##         two-sided
##          midp.exact  fisher.exact  chi.square
##   Male           NA            NA          NA
##   Female          0 2.045619e-205 6.3672e-147
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

RR=1.653 có nghĩa là xác suất để khách hàng nữ không đăng kí thành viên cao gấp 1.653 lần so với khách hàng nam.

library(vcd)
library(DescTools)
# Dùng hàm OddsRatio() từ thư viện DescTools
or_result <- OddsRatio(cross_table)
cat("📌 Odds Ratio :", or_result, "\n")
## 📌 Odds Ratio : 204.8049

OR=1.653 có nghĩa là tỷ lệ để khách hàng nữ không đăng kí thành viên so với đăng kí cao gấp 1.653 lần so với tỷ lệ đó ở nam giới