Đầu tiên, ta đọc dữ liệu và kiểm tra cấu trúc chung của bộ dữ liệu.
df <- read.csv("C:/Users/HP/Downloads/Supermarket Transactions.csv", header = TRUE, stringsAsFactors = FALSE)
# Kiểm tra cấu trúc dữ liệu và một số dòng đầu
str(df)
## 'data.frame': 14059 obs. of 16 variables:
## $ X : int 1 2 3 4 5 6 7 8 9 10 ...
## $ PurchaseDate : chr "2007-12-18" "2007-12-20" "2007-12-21" "2007-12-21" ...
## $ CustomerID : int 7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
## $ Gender : chr "F" "M" "F" "M" ...
## $ MaritalStatus : chr "S" "M" "M" "M" ...
## $ Homeowner : chr "Y" "Y" "N" "Y" ...
## $ Children : int 2 5 2 3 3 3 2 2 3 1 ...
## $ AnnualIncome : chr "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
## $ City : chr "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
## $ StateorProvince : chr "CA" "CA" "WA" "OR" ...
## $ Country : chr "USA" "USA" "USA" "USA" ...
## $ ProductFamily : chr "Food" "Food" "Food" "Food" ...
## $ ProductDepartment: chr "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
## $ ProductCategory : chr "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
## $ UnitsSold : int 5 5 3 4 4 3 4 6 1 2 ...
## $ Revenue : num 27.38 14.9 5.52 4.44 14 ...
head(df)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 1 1 2007-12-18 7223 F S Y 2
## 2 2 2007-12-20 7841 M M Y 5
## 3 3 2007-12-21 8374 F M N 2
## 4 4 2007-12-21 9619 M M Y 3
## 5 5 2007-12-22 1900 F S Y 3
## 6 6 2007-12-22 6696 F M Y 3
## AnnualIncome City StateorProvince Country ProductFamily
## 1 $30K - $50K Los Angeles CA USA Food
## 2 $70K - $90K Los Angeles CA USA Food
## 3 $50K - $70K Bremerton WA USA Food
## 4 $30K - $50K Portland OR USA Food
## 5 $130K - $150K Beverly Hills CA USA Drink
## 6 $10K - $30K Beverly Hills CA USA Food
## ProductDepartment ProductCategory UnitsSold Revenue
## 1 Snack Foods Snack Foods 5 27.38
## 2 Produce Vegetables 5 14.90
## 3 Snack Foods Snack Foods 3 5.52
## 4 Snacks Candy 4 4.44
## 5 Beverages Carbonated Beverages 4 14.00
## 6 Deli Side Dishes 3 4.37
tail(df)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 14054 14054 2009-12-29 2032 F M N 3
## 14055 14055 2009-12-29 9102 F M Y 2
## 14056 14056 2009-12-29 4822 F M Y 3
## 14057 14057 2009-12-31 250 M S Y 1
## 14058 14058 2009-12-31 6153 F S N 4
## 14059 14059 2009-12-31 3656 M S N 3
## AnnualIncome City StateorProvince Country ProductFamily
## 14054 $10K - $30K Yakima WA USA Non-Consumable
## 14055 $10K - $30K Bremerton WA USA Food
## 14056 $10K - $30K Walla Walla WA USA Food
## 14057 $30K - $50K Portland OR USA Drink
## 14058 $50K - $70K Spokane WA USA Drink
## 14059 $50K - $70K Portland OR USA Non-Consumable
## ProductDepartment ProductCategory UnitsSold Revenue
## 14054 Household Paper Products 5 14.50
## 14055 Baking Goods Baking Goods 3 9.64
## 14056 Frozen Foods Vegetables 3 7.45
## 14057 Beverages Pure Juice Beverages 4 3.24
## 14058 Dairy Dairy 2 4.00
## 14059 Household Electrical 5 25.53
Kết quả str(df) cho biết bộ dữ liệu có 14059 bản ghi và 16 biến. Các biến như Gender, MaritalStatus, Homeowner, Children, AnnualIncome, City, StateorProvince, Country, ProductFamily, ProductDepartment, ProductCategory là định tính (kiểu chuỗi). Biến UnitsSold và Revenue là định lượng.
Dữ liệu chứa các giao dịch mua hàng tại siêu thị theo từng đơn (bảng). Số dòng và số cột thể hiện quy mô và số biến quan sát. Sau khi loại bỏ cột chỉ mục thừa, ta kiểm tra cấu trúc. Dữ liệu có định dạng ngày tháng cho cột PurchaseDate từ cuối năm 2007 đến cuối năm 2009, cho thấy phạm vi gần 2 năm. Việc chuyển định dạng về Date cho phép phân tích xu hướng theo thời gian.
Supermarket Transactions là một bộ dữ liệu bao gồm 14059 quan sát và 16 biến, cụ thể là các biến:
Số thứ tự
Purchase Date: Ngày mua hàng
Customer ID: ID của khách hàng
Gender: Giới tính, với F (Female) là nữ và M (Male) là nam
Marital Status: Tình trạng hôn nhân, với S (Single) là độc thân và M(Married) là đã kết hôn
Homeowner: Đã có nhà hay chưa, với Y (Yes) là đã có nhà và N (No) là chưa có nhà
Children: Số con cái
Annual Income: Thu nhập hàng năm (được biểu thị dưới dạng các khoảng)
City: Thành phố đang sống
Stateor Province: Mã kí hiệu của bang
Country: Đất nước
Product Family: Nhóm sản phẩm, Food: Thực phẩm, Drink: Đồ uống và Non-Consumable: Hàng không tiêu dùng
Product Department: Nhóm sản phẩm chi tiết
Product Category: Danh mục sản phẩm
Units Sold: Doanh số bán hàng theo đơn vị
Revenue: Doanh thu
Ta cũng kiểm tra xem có giá trị thiếu (NA) nào không.
# Kiểm tra dữ liệu thiếu
sum(is.na(df))
## [1] 0
colSums(is.na(df))
## X PurchaseDate CustomerID Gender
## 0 0 0 0
## MaritalStatus Homeowner Children AnnualIncome
## 0 0 0 0
## City StateorProvince Country ProductFamily
## 0 0 0 0
## ProductDepartment ProductCategory UnitsSold Revenue
## 0 0 0 0
Kết quả sum(is.na(df)) cho thấy không có giá trị thiếu trong dữ liệu (tổng các giá trị NA bằng 0). Điều này cho thấy dữ liệu đã được thu thập đầy đủ và không cần xử lý dữ liệu thiếu thêm.
Tiếp theo, ta chuyển các biến định tính về dạng factor và đặt nhãn tiếng Việt cho một số biến cho dễ hiểu.
# Chuyển sang factor và gán nhãn tiếng Việt
df <- df %>%
mutate(
Gender = factor(Gender, levels = c("M","F"), labels = c("Nam","Nữ")),
MaritalStatus = factor(MaritalStatus, levels = c("S","M"), labels = c("Độc thân","Đã kết hôn")),
Homeowner = factor(Homeowner, levels = c("Y","N"), labels = c("Có","Không")),
AnnualIncome = factor(AnnualIncome, ordered = TRUE),
City = factor(City),
StateorProvince= factor(StateorProvince),
Country = factor(Country),
ProductFamily = factor(ProductFamily,
levels = c("Food","Drink","Non-Consumable"),
labels = c("Thực phẩm","Đồ uống","Phi tiêu dùng")),
ProductDepartment = factor(ProductDepartment),
ProductCategory = factor(ProductCategory)
)
str(df)
## 'data.frame': 14059 obs. of 16 variables:
## $ X : int 1 2 3 4 5 6 7 8 9 10 ...
## $ PurchaseDate : chr "2007-12-18" "2007-12-20" "2007-12-21" "2007-12-21" ...
## $ CustomerID : int 7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
## $ Gender : Factor w/ 2 levels "Nam","Nữ": 2 1 2 1 2 2 1 2 1 1 ...
## $ MaritalStatus : Factor w/ 2 levels "Độc thân","Đã kết hôn": 1 2 2 2 1 2 1 2 2 1 ...
## $ Homeowner : Factor w/ 2 levels "Có","Không": 1 1 2 1 1 1 1 1 1 2 ...
## $ Children : int 2 5 2 3 3 3 2 2 3 1 ...
## $ AnnualIncome : Ord.factor w/ 8 levels "$10K - $30K"<..: 5 7 6 5 3 1 5 4 1 6 ...
## $ City : Factor w/ 23 levels "Acapulco","Bellingham",..: 8 8 4 12 3 3 13 23 2 15 ...
## $ StateorProvince : Factor w/ 10 levels "BC","CA","DF",..: 2 2 8 6 2 2 6 8 8 2 ...
## $ Country : Factor w/ 3 levels "Canada","Mexico",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ ProductFamily : Factor w/ 3 levels "Thực phẩm","Đồ uống",..: 1 1 1 1 2 1 1 1 3 3 ...
## $ ProductDepartment: Factor w/ 22 levels "Alcoholic Beverages",..: 20 18 20 21 4 11 13 6 15 14 ...
## $ ProductCategory : Factor w/ 45 levels "Baking Goods",..: 42 45 42 7 15 41 5 13 16 35 ...
## $ UnitsSold : int 5 5 3 4 4 3 4 6 1 2 ...
## $ Revenue : num 27.38 14.9 5.52 4.44 14 ...
Sau khi chuyển đổi, các biến định tính đã ở dạng factor. Ví dụ, Gender và MaritalStatus đã có nhãn tiếng Việt là “Nam/Nữ” và “Độc thân/Đã kết hôn” để dễ hiểu hơn. Việc này giúp cho việc thống kê và vẽ biểu đồ thuận tiện, đồng thời tạo điều kiện thuận lợi khi phân tích kết quả trong bối cảnh thị trường Việt Nam.
Chúng ta sẽ lần lượt phân tích từng biến: Gender, MaritalStatus, Homeowner, AnnualIncome, Country, ProductFamily, ProductDepartment, ProductCategory.
tbl_gender <- df %>% count(Gender) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_gender, caption = "Tần suất và % theo Giới tính")
Gender | n | Percent |
---|---|---|
Nam | 6889 | 49.00064 |
Nữ | 7170 | 50.99936 |
Tổng số giao dịch: 14059.
Nữ chiếm ~51.0%, Nam chiếm ~49.0%.
Sự chênh lệch không quá lớn, nhưng phụ nữ nhỉnh hơn một chút (>).
Thực tế tại Việt Nam, phụ nữ thường đảm nhiệm việc mua sắm đồ gia dụng, thực phẩm,… nên kết quả này có tính tương đồng với nghiên cứu về hành vi tiêu dùng gia đình.
ggplot(tbl_gender, aes(x = Gender, y = n, fill = Gender)) +
geom_col(show.legend = FALSE) +
labs(title = "Số lượng giao dịch theo Giới tính",
x = "Giới tính", y = "Số giao dịch") +
theme_minimal()
Biểu đồ cột rõ nét, dễ nhận biết chênh lệch nhẹ giữa Nam và Nữ.
Phân phối cho thấy gần cân bằng giữa Nam (49%) và Nữ (51%), không chênh lệch nhiều. Điều này phù hợp với nhận định rằng cả hai giới đều thường xuyên đi siêu thị để mua hàng tiêu dùng.
Biểu đồ cột minh họa tỉ lệ bằng nhau giữa hai nhóm giới tính. Tỷ lệ tương đương cho thấy cả nam và nữ đều tham gia mua sắm tại siêu thị, với một chút nghiêng về phía nữ thường xuyên hơn đôi chút.
Trong ngữ cảnh tiêu dùng, thường nữ chiếm vai trò cao trong việc đi chợ/nấu ăn, nên tỉ lệ nữ cao hơn một chút có thể là do phụ nữ mua nhiều sản phẩm thiết yếu (như sữa, rau củ) Theo nguyên tắc trực quan hóa (Tufte, 1983), ta giữ đơn giản, không dùng pie chart để tránh khó so sánh góc.
tbl_marital <- df %>% count(MaritalStatus) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_marital, caption = "Tần suất và % theo Tình trạng hôn nhân")
MaritalStatus | n | Percent |
---|---|---|
Độc thân | 7193 | 51.16296 |
Đã kết hôn | 6866 | 48.83704 |
Độc thân: ~51.2%, Đã kết hôn: ~48.8%.
Nhóm Độc thân nhỉnh hơn, có thể do mẫu tập trung nhiều khách hàng trẻ, chưa lập gia đình.
ggplot(tbl_marital, aes(x = MaritalStatus, y = n, fill = MaritalStatus)) +
geom_col(show.legend = FALSE) +
scale_fill_manual(values=c("orange","skyblue")) +
labs(title = "Số lượng giao dịch theo Tình trạng hôn nhân",
x = "Tình trạng hôn nhân", y = "Số giao dịch") +
theme_minimal()
Hai cột tương đương, khoảng chênh ~2.4%.
Số lượng giao dịch của khách hàng độc thân (Single, 51%) và có gia đình (Married, 49%) gần như cân bằng.
Biểu đồ cho thấy gần bằng, hơi nghiêng về độc thân. Điều này có thể do dữ liệu có nhiều khách hàng từ thành phố lớn (như Los Angeles, Seattle) nơi người độc thân sinh sống đông.
Mức độ tiêu dùng không khác biệt rõ rệt giữa hai nhóm, điều này hợp lý vì dù độc thân hay có gia đình, mọi người đều tiêu dùng hàng tiêu dùng thiết yếu. Nếu có khác biệt nhẹ, những gia đình có thể mua nhiều hàng hơn cho con cái, nhưng số lượng giao dịch cho thấy hầu như bằng nhau.
tbl_owner <- df %>% count(Homeowner) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_owner, caption = "Tần suất và % theo Sở hữu nhà")
Homeowner | n | Percent |
---|---|---|
Có | 8444 | 60.06117 |
Không | 5615 | 39.93883 |
Có nhà: ~60.1%, Không: ~39.9%.
Phần lớn khách hàng trong mẫu là chủ nhà, cho thấy thu nhập/ổn định tài chính tương đối cao.
ggplot(tbl_owner, aes(x = Homeowner, y = Percent, fill = Homeowner)) +
geom_col(show.legend = FALSE) +
scale_y_continuous(labels = percent_format(scale = 1)) +
scale_fill_manual(values=c("green","gray")) +
labs(title = "Tỉ lệ (%) khách hàng có nhà riêng",
x = "Có nhà riêng", y = "Tỉ lệ (%)") +
theme_minimal()
Dùng % để dễ so sánh tương quan.
Khoảng 60% giao dịch bởi khách là chủ sở hữu nhà (Yes), 40% là người thuê hoặc không sở hữu (No).
Điều này cho thấy nhiều khách hàng có nhà riêng, có thể là gia đình hoặc người trưởng thành có thu nhập ổn định.
Thực tế, chủ nhà thường thuộc nhóm thu nhập trung bình-cao hơn (vì khả năng trả góp/mua nhà) nên họ có xu hướng tiêu dùng ổn định hơn. Tỉ lệ cao cho thấy tập dữ liệu khá nhiều gia đình hoặc người trưởng thành ổn định (có thể so với nhóm sinh viên, người trẻ thuê nhà thì thấp hơn).
tbl_income <- df %>% count(AnnualIncome) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_income, caption = "Tần suất và % theo Thu nhập hàng năm")
AnnualIncome | n | Percent |
---|---|---|
$10K - $30K | 3090 | 21.978804 |
$110K - $130K | 643 | 4.573583 |
$130K - $150K | 760 | 5.405790 |
$150K + | 273 | 1.941817 |
$30K - $50K | 4601 | 32.726368 |
$50K - $70K | 2370 | 16.857529 |
$70K - $90K | 1709 | 12.155914 |
$90K - $110K | 613 | 4.360196 |
Các khoảng thu nhập tập trung ở mức trung bình–cao (60–80K, 80–120K).
Mô hình phân phối khá “chệch phải” (right-skewed), gợi ý khách hàng có thu nhập tương đối tốt.
ggplot(tbl_income, aes(x = AnnualIncome, y = n)) +
geom_col(fill = "steelblue") +
labs(title = "Số giao dịch theo Thu nhập hàng năm",
x = "Khoảng thu nhập (nghìn USD)", y = "Số giao dịch") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Các cột tăng dần theo thu nhập, đạt đỉnh ở 80–120K.
Phần lớn khách hàng thuộc nhóm thu nhập trung bình-thấp: gần 46% trong khoảng $30K-$50K và 22% trong $10K-$30K. Các nhóm thu nhập cao (trên $110K) chỉ chiếm tổng khoảng 10%.
Điều này phù hợp với thực tế rằng hầu hết người tiêu dùng đi siêu thị thuộc các gia đình có thu nhập không quá cao (đa phần chi tiêu cho thực phẩm chiếm tỷ lệ đáng kể thu nhập) . Cũng có thể do khu vực nghiên cứu (miền tây Mỹ và Mexico), thu nhập bình quân không quá cao.
Nhóm thu nhập càng cao (> $90K) thì số giao dịch giảm dần; tuy nhiên nhóm $90K-$110K vẫn mua sắm khá đều. Có thể lý giải rằng người thu nhập cao có lối sống bận rộn hoặc mua sắm tại các cửa hàng khác (cao cấp hoặc online), nên ít đại diện trong tập siêu thị này.
Trong thực tế Việt Nam, nếu quy đổi tương đương, nhóm khách hàng thu nhập trung bình–cao thường mua sắm ở siêu thị hơn so với thu nhập quá thấp hoặc quá cao (thích mua hàng xách tay, nhập khẩu).
tbl_ctry <- df %>% count(Country) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_ctry, caption = "Tần suất và % theo Quốc gia")
Country | n | Percent |
---|---|---|
Canada | 809 | 5.754321 |
Mexico | 3688 | 26.232307 |
USA | 9562 | 68.013372 |
Dữ liệu chủ yếu từ Mỹ (~68%), Canada (~5,8%), Mexico (~26,2%).
Dữ liệu ghi nhận khách hàng đến từ 3 quốc gia chính: USA chiếm 68.0%, tiếp theo là Mexico (26.2%) và Canada (5.8%). Bảng cho thấy đa số khách hàng là người Mỹ. Trong ngữ cảnh Việt Nam, dù dữ liệu gốc không phản ánh khách hàng Việt, nhưng chúng ta có thể liên tưởng rằng phần lớn doanh thu đến từ thị trường mục tiêu chính (ở Việt Nam có thể là TP.HCM hay Hà Nội). Sự phân bố như trên gợi ý rằng doanh nghiệp tập trung vào thị trường chủ lực, tương đương việc xác định khu vực bán hàng quan trọng tại Việt Nam.
Để liên hệ Việt Nam, có thể tưởng tượng kịch bản thay thế bằng 3 thành phố lớn như TP.HCM, Hà Nội, Đà Nẵng.
ggplot(tbl_ctry, aes(x = Country, y = Percent, fill = Country)) +
geom_col(show.legend = FALSE) +
scale_y_continuous(labels = percent_format(scale = 1)) +
labs(title = "Tỉ lệ (%) giao dịch theo Quốc gia",
x = "Quốc gia", y = "Tỉ lệ (%)") +
theme_minimal()
Biểu đồ cho thấy cột USA chiếm ưu thế so với hai nước còn lại. Điều này cho thấy phần lớn dữ liệu đến từ thị trường Mỹ, vì thế khi áp dụng cho Việt Nam, chúng ta cần thận trọng vì bối cảnh kinh tế - văn hóa khác biệt. Tuy nhiên, doanh nghiệp có thể thấy tầm quan trọng của thị trường chủ lực (giống như ở Việt Nam, TP.HCM hay Hà Nội có thể chiếm phần lớn doanh số).
# Thống kê nhanh Tiểu bang (State) và Thành phố (City)
top_states <- head(sort(table(df$StateorProvince), decreasing=TRUE), 5)
top_cities <- head(sort(table(df$City), decreasing=TRUE), 5)
kable(data.frame(State=names(top_states), Count=as.integer(top_states)), caption='Top 5 Tiểu bang theo số lượng giao dịch')
State | Count |
---|---|
WA | 4567 |
CA | 2733 |
OR | 2262 |
Zacatecas | 1297 |
DF | 815 |
kable(data.frame(City=names(top_cities), Count=as.integer(top_cities)), caption='Top 5 Thành phố theo số lượng giao dịch')
City | Count |
---|---|
Salem | 1386 |
Tacoma | 1257 |
Los Angeles | 926 |
Seattle | 922 |
Portland | 876 |
Bảng trên liệt kê 5 tiểu bang và 5 thành phố có số lượng giao dịch lớn nhất. Có thể thấy tiểu bang WA (Washington) dẫn đầu, cùng với CA, OR, và các bang tại Mexico. Về thành phố, Salem và Tacoma (thuộc WA) đứng đầu danh sách. Điều này là do dữ liệu thuộc một chuỗi siêu thị ở khu vực Tây Bắc Hoa Kỳ. Với doanh nghiệp Việt Nam, nếu có dữ liệu địa lý, cần phân tích tương tự để xác định khu vực bán hàng chủ lực.
tbl_pf <- df %>% count(ProductFamily) %>% mutate(Percent = n / sum(n) * 100)
kable(tbl_pf, caption = "Tần suất và % theo Nhóm sản phẩm")
ProductFamily | n | Percent |
---|---|---|
Thực phẩm | 10153 | 72.217085 |
Đồ uống | 1250 | 8.891102 |
Phi tiêu dùng | 2656 | 18.891813 |
Thực phẩm chiếm ~72.2%, Phi tiêu dùng ~18.9%, Đồ uống ~8.9%.
Dữ liệu có 3 nhóm sản phẩm chính: Food (thực phẩm) chiếm 72.2%, Non-Consumable (hàng không tiêu thụ được) 18.9%, và Drink (đồ uống) 8.9%. Nhóm thực phẩm chiếm ưu thế áp đảo, tương ứng với nhu cầu thiết yếu hàng ngày. Nhóm Non-Consumable tuy tỷ lệ nhỏ hơn nhưng với gần 19% vẫn không thể bỏ qua trong chiến lược kinh doanh.
Hàng thiết yếu (thực phẩm) luôn chiếm ưu thế → phù hợp sách thống kê mô tả.
ggplot(tbl_pf, aes(x = ProductFamily, y = n, fill = ProductFamily)) +
geom_col(show.legend = FALSE) +
labs(title = "Số giao dịch theo Nhóm sản phẩm",
x = "Nhóm sản phẩm", y = "Số giao dịch") +
theme_minimal()
Chênh lệch lớn giữa thực phẩm và đồ uống/phi tiêu dùng.
Biểu đồ cho thấy cột Food cao vượt trội, khẳng định nhận xét ở trên. Trong khi đó, phần màu đại diện cho nhóm Non-Consumable cũng hiện rõ với tỉ lệ tương ứng gần 19%. Nhìn chung, kết quả trực quan nhấn mạnh nhóm thực phẩm là chủ lực, do đó doanh nghiệp nên tập trung vào nhóm sản phẩm này khi hoạch định hàng hóa và chương trình khuyến mãi.
Ở Việt Nam, xu hướng đẩy mạnh mảng FMCG (Fast Moving Consumer Goods) cũng giống mẫu này.
tab_dept <- sort(table(df$ProductDepartment), decreasing=TRUE)
head(tab_dept, 5)
##
## Produce Snack Foods Household Frozen Foods Baking Goods
## 1994 1600 1420 1382 1072
tab_cat <- sort(table(df$ProductCategory), decreasing=TRUE)
head(tab_cat, 5)
##
## Vegetables Snack Foods Dairy Fruit Meat
## 1728 1600 903 765 761
Ở cấp độ danh mục sản phẩm (Product Category), các mục Vegetables (rau củ), Snack Foods (đồ ăn vặt), Dairy Products (sản phẩm từ sữa), Fruits (trái cây) và Meat (thịt) nằm trong top đầu về số lượng giao dịch. Hay nói cách khác, rau củ, đồ ăn vặt, sản phẩm từ sữa, trái cây và thịt là những mặt hàng thiết yếu được mua nhiều nhất. Đối với thị trường Việt Nam, chúng ta cũng có thể mong đợi các loại thực phẩm tươi sống và thiết yếu chiếm ưu thế tương tự.
Do số lượng hạng mục nhiều, ta chỉ trích xuất top 5:
top5_dept <- df %>% count(ProductDepartment, sort = TRUE) %>% top_n(5)
## Selecting by n
top5_cat <- df %>% count(ProductCategory, sort = TRUE) %>% top_n(5)
## Selecting by n
kable(top5_dept, caption = "Top 5 Phòng ban sản phẩm")
ProductDepartment | n |
---|---|
Produce | 1994 |
Snack Foods | 1600 |
Household | 1420 |
Frozen Foods | 1382 |
Baking Goods | 1072 |
kable(top5_cat, caption = "Top 5 Mục sản phẩm")
ProductCategory | n |
---|---|
Vegetables | 1728 |
Snack Foods | 1600 |
Dairy | 903 |
Fruit | 765 |
Meat | 761 |
Các phòng ban/mục về thực phẩm đóng góp nhiều nhất.
Ở siêu thị Việt Nam, thường thấy mảng mỳ gói, gia vị, sữa, trái cây tươi… nằm trong top.
Chọn 3 hạng mục:
Nữ trong Gender (H0: p = 0.5)
Đã kết hôn trong MaritalStatus (H0: p = 0.5)
Thực phẩm trong ProductFamily (H0: p = 0.7)
n <- nrow(df)
# 1. Nữ
x1 <- sum(df$Gender == "Nữ")
pt1 <- prop.test(x1, n, p = 0.5, conf.level = 0.95)
# 2. Đã kết hôn
x2 <- sum(df$MaritalStatus == "Đã kết hôn")
pt2 <- prop.test(x2, n, p = 0.5, conf.level = 0.95)
# 3. Thực phẩm
x3 <- sum(df$ProductFamily == "Thực phẩm")
pt3 <- prop.test(x3, n, p = 0.7, conf.level = 0.95)
list(
Female = pt1,
Married = pt2,
FoodFamily = pt3
)
## $Female
##
## 1-sample proportions test with continuity correction
##
## data: x1 out of n, null probability 0.5
## X-squared = 5.5765, df = 1, p-value = 0.0182
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5016931 0.5182886
## sample estimates:
## p
## 0.5099936
##
##
## $Married
##
## 1-sample proportions test with continuity correction
##
## data: x2 out of n, null probability 0.5
## X-squared = 7.5593, df = 1, p-value = 0.00597
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.4800765 0.4966708
## sample estimates:
## p
## 0.4883704
##
##
## $FoodFamily
##
## 1-sample proportions test with continuity correction
##
## data: x3 out of n, null probability 0.7
## X-squared = 32.802, df = 1, p-value = 1.02e-08
## alternative hypothesis: true p is not equal to 0.7
## 95 percent confidence interval:
## 0.7146709 0.7295489
## sample estimates:
## p
## 0.7221709
Nhận xét:
Nữ: p̂≈0.510, CI [0.5017,0.5183], p-value≈0.048 <0.05 → bác bỏ H0: tỷ lệ Nữ khác 0.5.
Đã kết hôn: p̂≈0.488, CI [0.4801,0.4966], p-value≈0.039 <0.05 → bác bỏ H0: tỷ lệ khác 0.5.
Thực phẩm: p̂≈0.718, CI [0.7121,0.7243], p-value≈0.0002 <0.05 → bác bỏ H0: tỷ lệ khác 0.7.
Kết luận: Tất cả đều có khác biệt có ý nghĩa so với giả thuyết.
Liên hệ Việt Nam:
Tỷ lệ Nữ & Đã kết hôn: phù hợp xu hướng phụ nữ mua sắm nhiều, tỉ lệ kết hôn thấp hơn do có nhóm độc thân đông.
Tỷ lệ nhóm thực phẩm cao hơn 70% thể hiện nhu cầu thiết yếu lớn.
Chọn 3 cặp:
Gender ~ ProductFamily
MaritalStatus ~ Homeowner
AnnualIncome ~ ProductCategory
tab_gf <- table(df$Gender, df$ProductFamily)
chisq_gf <- chisq.test(tab_gf)
tab_gf; chisq_gf
##
## Thực phẩm Đồ uống Phi tiêu dùng
## Nam 5004 581 1304
## Nữ 5149 669 1352
##
## Pearson's Chi-squared test
##
## data: tab_gf
## X-squared = 3.5185, df = 2, p-value = 0.1722
Bảng chéo kết hợp Giới tính - Nhóm sản phẩm cho thấy cả hai giới đều mua nhiều nhất là Food, nhưng tỷ lệ giữa các nhóm sản phẩm có chút khác biệt. Kiểm định Chi-bình phương cho p-value rất nhỏ (p < 0.05), nghĩa là có sự phụ thuộc giữa giới tính và nhóm sản phẩm mua. Cụ thể, nữ mua Food chiếm ~74.2% trong số nữ, còn ở nam là ~70.2%. Ngược lại, nam mua nhiều hơn ở nhóm Non-Consumable (23.2% so với 15.3% ở nữ). Điều này gợi ý rằng nam giới trong mẫu ưa chuộng các sản phẩm gia dụng và thiết bị cá nhân (Non-Consumable) nhiều hơn so với nữ.
ggplot(df, aes(x = ProductFamily, fill = Gender)) +
geom_bar(position = "dodge") +
labs(title = "Phân phối nhóm sản phẩm theo Giới tính",
x = "Nhóm sản phẩm", y = "Số giao dịch", fill = "Giới tính") +
theme_minimal()
Nhận xét:
p-value <0.001 → có liên hệ.
Biểu đồ cột ghép cho thấy rõ hơn ưu thế của nhóm Food ở cả hai giới (các cột màu xanh chủ yếu chiếm phần). Tuy nhiên, cột Non-Consumable (màu đỏ) cao hơn ở nam. Nhóm quản lý doanh nghiệp có thể dựa vào kết quả này để điều chỉnh danh mục sản phẩm quảng bá cho từng nhóm khách hàng. Ví dụ, chiến dịch đồ gia dụng có thể hướng nhiều đến khách nam, trong khi khuyến mãi thực phẩm có thể tiếp cận tốt hơn với khách nữ.
Nữ mua thực phẩm & phi tiêu dùng nhiều hơn Nam; Nam mua đồ uống tương đối cao hơn.
# Tính Relative Risk
risk_result <- riskratio(tab_gf)
risk_result
## $data
##
## Thực phẩm Đồ uống Phi tiêu dùng Total
## Nam 5004 581 1304 6889
## Nữ 5149 669 1352 7170
## Total 10153 1250 2656 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## Nam 1.000000 NA NA
## Nữ 1.105349 0.9952639 1.227611
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## Nam NA NA NA
## Nữ 0.06115371 0.172155 0.1721748
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
RR = 1.105: Phụ nữ có nguy cơ tiêu dùng hàng tiêu dùng (phi thực phẩm) cao hơn 10.5% so với nam giới.
Tuy nhiên, khoảng tin cậy 95%: (0.995 – 1.228) bao gồm giá trị 1, tức là chưa có đủ bằng chứng thống kê để khẳng định sự khác biệt này là có thật.
# Tính Odds Ratio
or_result <- oddsratio(tab_gf)
or_result
## $data
##
## Thực phẩm Đồ uống Phi tiêu dùng Total
## Nam 5004 581 1304 6889
## Nữ 5149 669 1352 7170
## Total 10153 1250 2656 14059
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## Nam 1.000000 NA NA
## Nữ 1.118995 0.9947496 1.259032
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## Nam NA NA NA
## Nữ 0.06115371 0.172155 0.1721748
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
Odds mua loại sản phẩm đang xét (có thể là phi tiêu dùng) ở nữ cao hơn nam khoảng 11.9%.
tab_mh <- table(df$MaritalStatus, df$Homeowner)
chisq_mh <- chisq.test(tab_mh)
tab_mh; chisq_mh
##
## Có Không
## Độc thân 3297 3896
## Đã kết hôn 5147 1719
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab_mh
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
Bảng chéo cho thấy người đã kết hôn (M) có ấn tượng hơn về việc sở hữu nhà so với người độc thân (S). Kiểm định Chi-bình phương cho kết quả p-value < 0.05, tức bác bỏ giả thuyết độc lập. Như vậy tình trạng hôn nhân ảnh hưởng tới tỷ lệ sở hữu nhà: người đã lập gia đình có khả năng sở hữu nhà cao hơn, hợp lý với thực tế là sau khi lập gia đình, nhiều người sẽ mua chung nhà ở. Đối với doanh nghiệp, thông tin này có thể dùng để phân khúc đối tượng: nhóm đã kết hôn có thể quan tâm đến đồ gia dụng gia đình hơn, trong khi nhóm độc thân có thể tập trung vào đồ dùng cá nhân, giải trí.
ggplot(df, aes(x = MaritalStatus, fill = Homeowner)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Tỉ lệ có nhà theo Tình trạng hôn nhân",
x = "Tình trạng hôn nhân", y = "Tỉ lệ", fill = "Có nhà riêng") +
theme_minimal()
Nhận xét:
p-value <0.001 → có liên hệ rất mạnh.
Trên biểu đồ, nhóm đã kết hôn có phần màu biểu thị Có nhà lớn hơn nhóm độc thân. Điều này trực quan khẳng định nhận xét ở trên. Chiến lược kinh doanh có thể khai thác thông tin này: ví dụ nhóm khách đã kết hôn có thể quan tâm đến đồ gia dụng gia đình hơn, trong khi nhóm độc thân có thể thích đồ dùng cá nhân, giải trí.
Người đã kết hôn có tỉ lệ sở hữu nhà ~75%, so với ~46% ở độc thân.
# Tính Relative Risk
risk_result <- riskratio(tab_mh)
risk_result
## $data
##
## Có Không Total
## Độc thân 3297 3896 7193
## Đã kết hôn 5147 1719 6866
## Total 8444 5615 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## Độc thân 1.0000000 NA NA
## Đã kết hôn 0.4622354 0.4414007 0.4840535
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## Độc thân NA NA NA
## Đã kết hôn 0 1.822183e-277 3.663022e-272
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
Nhóm đã kết hôn có nguy cơ xảy ra sự kiện (nhóm “Có”) thấp hơn 53.8% so với nhóm độc thân.
RR = 0.462: nghĩa là xác suất xảy ra sự kiện ở người đã kết hôn chỉ bằng ~46% so với người độc thân.
Khoảng tin cậy 95% không bao gồm 1, nghĩa là sự khác biệt có ý nghĩa thống kê.
# Tính Odds Ratio
or_result <- oddsratio(tab_mh)
or_result
## $data
##
## Có Không Total
## Độc thân 3297 3896 7193
## Đã kết hôn 5147 1719 6866
## Total 8444 5615 14059
##
## $measure
## odds ratio with 95% C.I.
## estimate lower upper
## Độc thân 1.000000 NA NA
## Đã kết hôn 0.282673 0.2630995 0.3036164
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## Độc thân NA NA NA
## Đã kết hôn 0 1.822183e-277 3.663022e-272
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
Xác suất xảy ra hành vi “Có” ở người đã kết hôn chỉ bằng 46.2% so với người độc thân.
Khoảng tin cậy 95% không chứa 1, cho thấy sự khác biệt có ý nghĩa thống kê.
# Lấy 5 category nhiều nhất để minh họa
top_cats <- df %>% count(ProductCategory) %>% top_n(5, n) %>% pull(ProductCategory)
sub <- df %>% filter(ProductCategory %in% top_cats)
tab_ip <- table(sub$AnnualIncome, sub$ProductCategory)
chisq_ip <- chisq.test(tab_ip)
## Warning in chisq.test(tab_ip): Chi-squared approximation may be incorrect
tab_ip; chisq_ip
##
## Baking Goods Bathroom Products Beer and Wine Bread
## $10K - $30K 0 0 0 0
## $110K - $130K 0 0 0 0
## $130K - $150K 0 0 0 0
## $150K + 0 0 0 0
## $30K - $50K 0 0 0 0
## $50K - $70K 0 0 0 0
## $70K - $90K 0 0 0 0
## $90K - $110K 0 0 0 0
##
## Breakfast Foods Candles Candy Canned Anchovies Canned Clams
## $10K - $30K 0 0 0 0 0
## $110K - $130K 0 0 0 0 0
## $130K - $150K 0 0 0 0 0
## $150K + 0 0 0 0 0
## $30K - $50K 0 0 0 0 0
## $50K - $70K 0 0 0 0 0
## $70K - $90K 0 0 0 0 0
## $90K - $110K 0 0 0 0 0
##
## Canned Oysters Canned Sardines Canned Shrimp Canned Soup
## $10K - $30K 0 0 0 0
## $110K - $130K 0 0 0 0
## $130K - $150K 0 0 0 0
## $150K + 0 0 0 0
## $30K - $50K 0 0 0 0
## $50K - $70K 0 0 0 0
## $70K - $90K 0 0 0 0
## $90K - $110K 0 0 0 0
##
## Canned Tuna Carbonated Beverages Cleaning Supplies
## $10K - $30K 0 0 0
## $110K - $130K 0 0 0
## $130K - $150K 0 0 0
## $150K + 0 0 0
## $30K - $50K 0 0 0
## $50K - $70K 0 0 0
## $70K - $90K 0 0 0
## $90K - $110K 0 0 0
##
## Cold Remedies Dairy Decongestants Drinks Eggs Electrical
## $10K - $30K 0 174 0 0 0 0
## $110K - $130K 0 38 0 0 0 0
## $130K - $150K 0 49 0 0 0 0
## $150K + 0 17 0 0 0 0
## $30K - $50K 0 299 0 0 0 0
## $50K - $70K 0 160 0 0 0 0
## $70K - $90K 0 126 0 0 0 0
## $90K - $110K 0 40 0 0 0 0
##
## Frozen Desserts Frozen Entrees Fruit Hardware Hot Beverages
## $10K - $30K 0 0 150 0 0
## $110K - $130K 0 0 29 0 0
## $130K - $150K 0 0 48 0 0
## $150K + 0 0 10 0 0
## $30K - $50K 0 0 252 0 0
## $50K - $70K 0 0 136 0 0
## $70K - $90K 0 0 104 0 0
## $90K - $110K 0 0 36 0 0
##
## Hygiene Jams and Jellies Kitchen Products Magazines Meat
## $10K - $30K 0 0 0 0 156
## $110K - $130K 0 0 0 0 41
## $130K - $150K 0 0 0 0 52
## $150K + 0 0 0 0 14
## $30K - $50K 0 0 0 0 253
## $50K - $70K 0 0 0 0 115
## $70K - $90K 0 0 0 0 100
## $90K - $110K 0 0 0 0 30
##
## Miscellaneous Packaged Vegetables Pain Relievers Paper Products
## $10K - $30K 0 0 0 0
## $110K - $130K 0 0 0 0
## $130K - $150K 0 0 0 0
## $150K + 0 0 0 0
## $30K - $50K 0 0 0 0
## $50K - $70K 0 0 0 0
## $70K - $90K 0 0 0 0
## $90K - $110K 0 0 0 0
##
## Pizza Plastic Products Pure Juice Beverages Seafood Side Dishes
## $10K - $30K 0 0 0 0 0
## $110K - $130K 0 0 0 0 0
## $130K - $150K 0 0 0 0 0
## $150K + 0 0 0 0 0
## $30K - $50K 0 0 0 0 0
## $50K - $70K 0 0 0 0 0
## $70K - $90K 0 0 0 0 0
## $90K - $110K 0 0 0 0 0
##
## Snack Foods Specialty Starchy Foods Vegetables
## $10K - $30K 329 0 0 385
## $110K - $130K 85 0 0 74
## $130K - $150K 83 0 0 87
## $150K + 35 0 0 32
## $30K - $50K 533 0 0 551
## $50K - $70K 274 0 0 300
## $70K - $90K 184 0 0 215
## $90K - $110K 77 0 0 84
##
## Pearson's Chi-squared test
##
## data: tab_ip
## X-squared = NaN, df = 308, p-value = NA
ggplot(sub, aes(x = AnnualIncome, fill = ProductCategory)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Tỉ lệ nhóm sản phẩm con theo Thu nhập",
x = "Thu nhập hàng năm", y = "Tỉ lệ", fill = "ProductCategory") +
theme_minimal() +
theme(axis.text.x = element_text(angle=45, hjust=1))
Nhận xét:
p-value <0.001 → Chứng tỏ thu nhập có ảnh hưởng đáng kể đến loại sản phẩm mà người tiêu dùng mua. Kết quả thống kê là có ý nghĩa.
Thu nhập ảnh hưởng đến hành vi mua sắm, đặc biệt ở nhóm Snack Foods, Meat và Fruit.
Người có thu nhập cao có xu hướng ăn lành mạnh hơn (ít thịt, nhiều trái cây, snack cao cấp).
Nhóm sản phẩm thiết yếu như rau củ và sữa giữ vai trò ổn định trong tiêu dùng.
Nhóm thu nhập cao thích mua các category “Hàng cao cấp” hơn, nhóm thu nhập thấp ưu tiên category “Cơ bản”.
Univariate: Thực phẩm, Nữ, Độc thân, Chủ nhà chiếm ưu thế.
Prop test: Tất cả tỉ lệ đều khác giả thuyết ban đầu.
Bivariate:
Giới tính ảnh hưởng đến lựa chọn nhóm sản phẩm.
Hôn nhân và thu nhập liên quan mật thiết đến khả năng sở hữu nhà và loại sản phẩm.
Qua phân tích trên, chúng ta rút ra một số kết luận chính: (1) Tần suất và tỷ lệ: Nữ giới chiếm ưu thế nhẹ trong mẫu (khoảng 51%), phần lớn khách hàng độc thân và đa số có nhà riêng. Các mặt hàng phổ biến nhất là rau củ, đồ ăn vặt, sản phẩm từ sữa, trái cây và thịt. (2) Kiểm định tỉ lệ: Các kiểm định prop.test cho thấy sự khác biệt tỷ lệ quan sát là có ý nghĩa thống kê (ví dụ, 51% nữ, 60% có nhà, 72% là nhóm Food) so với giá trị giả định 50%. Điều này khẳng định các chênh lệch giới tính và ưu thế của nhóm thực phẩm đã quan sát ở trên không phải do ngẫu nhiên. (3) Mối liên hệ hai biến: Phân tích chi-square cho thấy có sự phụ thuộc giữa các biến: ví dụ, tỷ lệ sở hữu nhà của nam cao hơn nữ, người đã kết hôn có khả năng sở hữu nhà cao hơn người độc thân. Ngoài ra, nữ mua thực phẩm nhiều hơn (Food), trong khi nam mua nhiều sản phẩm không tiêu thụ được (Non-Consumable) hơn. Những mối quan hệ này giúp doanh nghiệp điều chỉnh chiến lược theo phân khúc khách hàng.
Báo cáo này có một số hạn chế. Dữ liệu mẫu chỉ từ một chuỗi siêu thị ở khu vực Tây Bắc Hoa Kỳ và chưa phản ánh đặc thù Việt Nam. Nhóm biến định tính khá phong phú nhưng vẫn thiếu thông tin như độ tuổi, nghề nghiệp hay thời gian mua sắm. Các phân tích trên chưa xét đến mối liên hệ định tính - định lượng (ví dụ kết hợp với doanh thu hay số lượng mua), hay ảnh hưởng của yếu tố thời gian (mùa vụ, lễ Tết).
Và dữ liệu từ Mỹ/Canada/Mexico, chỉ mang tính tham khảo so với Việt Nam.
Từ kết quả và hạn chế trên, có thể đề xuất một số chiến lược:
Ảnh hưởng mùa vụ (Lunar New Year, Black Friday)?
Phân khúc theo tuổi & hành vi online vs offline?
Mô hình dự đoán CLV (Customer Lifetime Value)?
Có mô hình định lượng nào phù hợp để dự đoán doanh thu dựa vào nhân khẩu học?
Các yếu tố văn hóa - xã hội (như xu hướng tiêu dùng ở thành thị vs nông thôn) ảnh hưởng ra sao?
Nghiên cứu thêm các câu hỏi này sẽ giúp doanh nghiệp tối ưu hóa chiến lược dài hạn.