#Sử dụng lệnh read.csv để đọc file dữ liệu đã được cung cấp
nt <- read.csv("C:/Users/Admin/OneDrive/Desktop/TMT/DATA FOR R/WEEK 1/Supermarket Transactions.csv", header = T)
#Đọc cấu trúc bộ dữ liệu đã được đưa vào ban đầu
str(nt)
## '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 ...
Mô tả bằng lời bộ dữ liệu trên:
Bộ dữ liệu gồm 14,059 dòng và 16 biến, phản ánh thông tin chi tiết về các giao dịch mua hàng của khách hàng.
Các biến có thể được phân thành ba nhóm chính: (1) thông tin
khách hàng như CustomerID, Gender,
MaritalStatus, Homeowner,
Children và AnnualIncome; (2) thông tin địa lý
bao gồm City, StateorProvince và
Country; và (3) thông tin sản phẩm và giao dịch như
PurchaseDate, ProductFamily,
ProductDepartment, ProductCategory,
UnitsSold và Revenue. Trong đó, các biến định
danh và định lượng như CustomerID, UnitsSold,
Revenue có kiểu số nguyên hoặc số thực, trong khi đa số các
biến còn lại là chuỗi ký tự.
Một số biến cần được xử lý thêm trước khi phân tích, chẳng hạn
như PurchaseDate nên được chuyển sang kiểu ngày
(Date) để phục vụ các phân tích theo thời gian. Biến
AnnualIncome hiện ở dạng chuỗi mô tả khoảng thu nhập, cần
được mã hóa lại thành biến thứ bậc để phản ánh đúng bản chất định
lượng.
Các biến phân loại như giới tính, tình trạng hôn nhân hay loại
sản phẩm nên được chuyển thành kiểu factor trong R để phục
vụ mô hình hóa. Ngoài ra, biến X nhiều khả năng chỉ là chỉ
số dòng hoặc ID tự sinh, không mang ý nghĩa phân tích, nên có thể được
loại bỏ. Tổng quan, dữ liệu có cấu trúc rõ ràng và đầy đủ để thực hiện
các phân tích hành vi mua hàng, phân khúc khách hàng hoặc đánh giá hiệu
quả sản phẩm.
Tiến hành xem chi tiết 10 dòng đầu và 10 dòng cuối của bộ dữ liệu trên
#Xem 10 dòng đầu của bộ dữ liệu
head(nt)
## 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
Dữ liệu mẫu gồm 6 dòng đầu tiên trong tổng số 14,059 dòng của bộ dữ liệu, với đầy đủ 16 biến thể hiện các thông tin liên quan đến khách hàng và giao dịch mua hàng. Các cột hiển thị bao gồm: mã định danh (X), ngày mua hàng (PurchaseDate), mã khách hàng (CustomerID), giới tính (Gender), tình trạng hôn nhân (MaritalStatus), tình trạng sở hữu nhà (Homeowner), số lượng con (Children) và khoảng thu nhập hàng năm (AnnualIncome). Dữ liệu cho thấy sự đa dạng về nhân khẩu học, khi có cả khách hàng nam và nữ, tình trạng hôn nhân khác nhau, thu nhập dao động từ dưới $30K đến trên $130K, và số con từ 2 đến 5. Điều này cho thấy bộ dữ liệu có tiềm năng để phân tích hành vi tiêu dùng theo phân khúc khách hàng khác nhau.
Tiếp tục quan sát phần dữ liệu mở rộng, các biến còn lại gồm thông tin về địa lý và sản phẩm: City, StateorProvince, Country, ProductFamily, ProductDepartment, ProductCategory, cùng với số lượng bán (UnitsSold) và doanh thu (Revenue). Dữ liệu cho thấy các giao dịch diễn ra tại nhiều thành phố thuộc các bang khác nhau của Hoa Kỳ như California (CA), Washington (WA) và Oregon (OR), phản ánh phạm vi địa lý tương đối rộng. Về mặt sản phẩm, nhóm hàng hóa chủ yếu thuộc nhóm Food và Drink, với các bộ phận và danh mục con như Snack Foods, Produce, Deli, Beverages và Candy.
Số lượng sản phẩm bán ra dao động từ 3 đến 5 đơn vị mỗi giao dịch, với doanh thu tương ứng từ khoảng 4 đến 27 đô la, cho thấy sự chênh lệch tùy theo loại sản phẩm. Cách phân chia sản phẩm theo ba cấp độ: ProductFamily, ProductDepartment và ProductCategory giúp dữ liệu trở nên linh hoạt và chi tiết hơn cho việc phân tích danh mục sản phẩm, hành vi mua sắm, hoặc đánh giá hiệu suất bán hàng theo từng phân khúc. Nhìn chung, phần dữ liệu này bổ sung thông tin quan trọng về sản phẩm và vùng địa lý, làm cơ sở để thực hiện các phân tích đa chiều kết hợp giữa nhân khẩu học, vị trí và chủng loại hàng hóa.
Tiến hành xem tiếp 10 dòng cuối của bộ dữ liệu
#Xem 10 dòng đầu của bộ dữ liệu
tail(nt,10)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 14050 14050 2009-12-28 1394 M M Y 0
## 14051 14051 2009-12-28 6251 M S N 4
## 14052 14052 2009-12-28 378 M S Y 1
## 14053 14053 2009-12-28 7234 F M Y 4
## 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
## 14050 $30K - $50K San Andres DF Mexico Food
## 14051 $50K - $70K Vancouver BC Canada Food
## 14052 $30K - $50K Spokane WA USA Food
## 14053 $30K - $50K Spokane WA USA Food
## 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
## 14050 Deli Meat 4 7.15
## 14051 Dairy Dairy 5 19.95
## 14052 Dairy Dairy 5 28.08
## 14053 Deli Side Dishes 5 6.80
## 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
Phân tích 10 dòng cuối cùng của bộ dữ liệu cho thấy các giao dịch diễn ra vào cuối tháng 12 năm 2009, trải rộng tại nhiều khu vực địa lý, bao gồm cả Hoa Kỳ (WA, OR), Canada (BC) và Mexico (DF). Điều này phản ánh việc mở rộng thị trường ra ngoài nước Mỹ, với khách hàng quốc tế cũng tham gia vào hoạt động mua sắm. Nhóm sản phẩm trong các giao dịch này khá đa dạng, thuộc cả nhóm tiêu dùng (Food, Drink) và phi tiêu dùng (Non-Consumable), với các danh mục cụ thể như Meat, Dairy, Side Dishes, Paper Products, Frozen Foods, và Electrical.
Về mặt hành vi khách hàng, các biến nhân khẩu học vẫn cho thấy sự đa dạng với cả nam và nữ, tình trạng hôn nhân khác nhau và nhiều mức thu nhập khác nhau, từ $10K - $30K đến $50K - $70K. Số con dao động từ 0 đến 4, cho thấy dữ liệu bao phủ cả nhóm khách hàng độc thân lẫn gia đình.
Số lượng hàng hóa được bán trong mỗi giao dịch dao động từ 2 đến 5 đơn vị, với doanh thu tương ứng từ 3.24 đến 28.08 USD. Nhìn chung, các sản phẩm có giá trị tương đối nhỏ, phù hợp với đặc điểm của ngành bán lẻ. Việc xuất hiện những sản phẩm thuộc nhóm Non-Consumable như Electrical hay Paper Products cho thấy bộ dữ liệu không chỉ giới hạn ở thực phẩm mà còn bao gồm cả các mặt hàng gia dụng, giúp mở rộng phạm vi phân tích hành vi tiêu dùng đa dạng hơn.
Tiến hành chọn tất các biến định tính có sẵn trong bộ dữ liệu và đưa ra một bộ mới để không ảnh hưởng đến bộ dữ liệu gốc ban đầu. Kiểm tra xem có xuất hiện giá trị trống [N/A] trong bộ dữ liệu hay không.
#Chọn các biến định tính
bdt<- c("PurchaseDate","CustomerID","Gender","MaritalStatus","Homeowner","City","StateorProvince","Country","ProductFamily","ProductDepartment","ProductCategory", "AnnualIncome")
#Tạo bộ dữ liệu mới chỉ có biến định tính
dt1 <- nt[,bdt]
#Kiểm tra xem bộ dữ liệu mới có xuất hiện giá trị rỗng hay không
any(is.na(dt1))
## [1] FALSE
Dựa trên kết quả mà R trả ra,có thể khẳng định rằng trong bộ dữ liệu chứa biến định tính không xuất hiện giá trị rỗng [N.A]
Chuyển đổi các biến cần thiết sang kiểu factor nếu chúng chưa phải là factor.
#Kiểm tra bộ dữ liệu của toàn biến
str(dt1)
## 'data.frame': 14059 obs. of 12 variables:
## $ 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" ...
## $ 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" ...
## $ AnnualIncome : chr "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
#Kiểm tra từng cột riêng, cột nào là factor
sapply(dt1, is.factor)
## PurchaseDate CustomerID Gender MaritalStatus
## FALSE FALSE FALSE FALSE
## Homeowner City StateorProvince Country
## FALSE FALSE FALSE FALSE
## ProductFamily ProductDepartment ProductCategory AnnualIncome
## FALSE FALSE FALSE FALSE
#Kiểm tra dữ liệu cụ thể của từng biến trong dữ liệu
sapply(dt1, class)
## PurchaseDate CustomerID Gender MaritalStatus
## "character" "integer" "character" "character"
## Homeowner City StateorProvince Country
## "character" "character" "character" "character"
## ProductFamily ProductDepartment ProductCategory AnnualIncome
## "character" "character" "character" "character"
Đoạn lệnh ‘sapply(dt, is.factor)’ được sử dụng để kiểm tra từng cột trong dataframe df xem có phải là kiểu dữ liệu factor hay không. Kết quả trả về cho thấy tất cả các cột trong dataframe đều trả về giá trị FALSE, có nghĩa là không có cột nào được định nghĩa dưới dạng factor. Điều này đồng nghĩa với việc các cột, dù có thể mang tính chất phân loại như Gender, MaritalStatus, hay City, hiện tại đang được lưu dưới dạng các kiểu dữ liệu khác như character hoặc numeric thay vì factor. Việc không sử dụng factor cho các biến phân loại có thể ảnh hưởng đến một số phân tích hoặc mô hình hóa dữ liệu, vì factor giúp R nhận biết rõ các nhóm phân loại và xử lý chúng hiệu quả hơn. Do đó, trong nhiều trường hợp, việc chuyển các cột này sang kiểu factor là cần thiết để tận dụng tối đa các tính năng xử lý biến phân loại trong R.
Đoạn lệnh sapply(dt, class) được sử dụng để xác định
kiểu dữ liệu của từng cột trong dataframe df. Kết quả cho
thấy hầu hết các cột như PurchaseDate, Gender,
MaritalStatus, Homeowner, City,
StateorProvince, Country,
ProductFamily, ProductDepartment và
ProductCategory đều có kiểu dữ liệu là
character, trong khi cột CustomerID là kiểu
integer. Điều này cho thấy các biến mang tính phân loại
trong dữ liệu, thay vì được lưu dưới dạng factor – kiểu dữ liệu chuyên
biệt dành cho các biến phân loại trong R, thì lại đang được lưu trữ dưới
dạng chuỗi ký tự thông thường. Việc này có thể ảnh hưởng đến hiệu quả và
tính chính xác trong quá trình phân tích dữ liệu, vì các hàm và mô hình
trong R thường ưu tiên xử lý biến phân loại dưới dạng factor để nhận
biết và phân biệt các nhóm một cách rõ ràng hơn. Do đó, việc chuyển đổi
các cột có kiểu character này sang factor sẽ giúp tối ưu hóa quy trình
phân tích, đồng thời tận dụng đầy đủ các lợi ích mà kiểu dữ liệu factor
mang lại trong các mô hình thống kê và học máy.
Tiếp tục chuyển các biến không phải factor thành định dạng factor
dt <- data.frame(lapply(dt1, as.factor))
Đoạn lệnh dtfactor <- data.frame(lapply(dt, as.factor)) được
sử dụng để chuyển đổi toàn bộ các cột trong dataframe ntdt
sang kiểu dữ liệu factor. Cụ thể, hàm
lapply(ntdt, as.factor) sẽ lần lượt áp dụng hàm
as.factor cho từng cột trong dataframe ntdt, biến đổi tất
cả các cột thành factor, rồi kết quả được gán lại thành một dataframe
mới dtfactor.
Kết quả trả về cho thấy tất cả các cột trong dtfactor đều có kiểu là factor, bao gồm các biến như PurchaseDate, CustomerID, Gender, MaritalStatus, Homeowner, City` và các cột khác liên quan đến địa lý hoặc sản phẩm. Điều này có nghĩa là sau khi thực hiện câu lệnh, tất cả các biến phân loại trước đây (một số có thể đang ở dạng character hoặc integer) đã được chuẩn hóa về cùng một kiểu dữ liệu factor – kiểu dữ liệu chuyên dùng để biểu diễn các biến phân loại trong R.
Việc chuyển toàn bộ các cột sang factor giúp tối ưu hóa quá trình phân tích thống kê và mô hình hóa, bởi R sẽ hiểu rõ rằng các biến này là các nhóm phân loại chứ không phải dữ liệu số hay chuỗi ký tự thông thường. Điều này cũng giúp tránh nhầm lẫn và xử lý sai khi dùng các hàm hoặc mô hình yêu cầu biến phân loại dưới dạng factor. Tuy nhiên, nếu có các biến số thực sự mang tính liên tục hoặc định lượng, việc chuyển hết sang factor có thể không phù hợp, nên cần kiểm tra kỹ trước khi áp dụng trên toàn bộ dataframe.
Biến Gender với hai mức giá trị là Female và Male là một biến phân loại (categorical variable) dùng để biểu thị giới tính của một cá nhân hoặc khách hàng trong bộ dữ liệu.
Ý nghĩa của biến này là để phân nhóm hoặc phân loại đối tượng theo giới tính, giúp phân tích các đặc điểm, hành vi, xu hướng, hoặc các yếu tố liên quan khác dựa trên sự khác biệt giới tính. Ví dụ, trong nghiên cứu thị trường, biến Gender có thể giúp xác định sự khác biệt trong thói quen mua sắm giữa nam và nữ, từ đó đưa ra các chiến lược marketing phù hợp.
Về mặt dữ liệu, khi biến Gender được định nghĩa dưới dạng factor với hai mức là Female và Male, điều đó giúp R nhận biết đây là biến phân loại với hai nhóm riêng biệt, thuận tiện cho việc phân tích, trực quan hóa và xây dựng các mô hình dự báo liên quan đến các nhóm này.
Tiến hành lập bảng tần số và phần trăm cho mỗi hạng mục biến
#Lập bảng tần số
gender_table<- table(dt1$Gender)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
GD <- table(dt1$Gender)/sum(nrow(dt1))
GD
##
## F M
## 0.5099936 0.4900064
# Cài đặt và nạp gói ggplot2 nếu chưa có
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
# Tạo bảng dữ liệu từ biến Gender
gender_df <- as.data.frame(table(dt1$Gender))
colnames(gender_df) <- c("Gender", "Count")
# Tính phần trăm
gender_df$Percent <- round(gender_df$Count / sum(gender_df$Count) * 100, 1)
gender_df$Label <- paste0(gender_df$Gender, " (", gender_df$Percent, "%)")
# Vẽ biểu đồ tròn
ggplot(gender_df, aes(x = "", y = Count, fill = Gender)) +
geom_bar(width = 1, stat = "identity", color = "white") +
coord_polar("y", start = 0) +
geom_text(aes(label = Label), position = position_stack(vjust = 0.5), size = 5) +
labs(title = "Biểu đồ tròn phân bố giới tính") +
scale_fill_manual(values = c("pink", "lightblue")) +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14))
Dữ liệu về biến Gender trong tập dữ liệu cho thấy sự phân bố giới tính khá cân bằng, với nhóm Female (F) chiếm khoảng 51.0% và nhóm Male (M) chiếm khoảng 49.0% tổng số quan sát. Sự chênh lệch giữa hai nhóm là rất nhỏ, chỉ khoảng 2%, cho thấy không có hiện tượng mất cân đối đáng kể giữa các hạng mục giới tính.
Từ bảng tần suất và biểu đồ tròn, có thể thấy Female là hạng mục chiếm ưu thế nhẹ, tuy nhiên mức độ khác biệt không lớn. Sự phân bố gần như đồng đều này là một yếu tố tích cực trong phân tích dữ liệu, giúp đảm bảo tính khách quan, tránh thiên lệch trong mô hình thống kê hoặc các kết luận rút ra từ dữ liệu. Điều này cũng tạo điều kiện thuận lợi cho việc so sánh, đánh giá và dự báo mà không cần áp dụng kỹ thuật điều chỉnh cho dữ liệu mất cân bằng.
MaritalStatus thể hiện tình trạng hôn nhân của
khách hàng, gồm hai giá trị là “M” (Married – đã kết hôn) và “S” (Single
– độc thân). Đây là một biến phân loại định tính, có thể ảnh hưởng đến
hành vi tiêu dùng của khách hàng. Những người đã kết hôn thường có xu
hướng mua sắm phục vụ cho gia đình hoặc con cái, trong khi người độc
thân có thể ưu tiên các sản phẩm phục vụ nhu cầu cá nhân. Do đó, biến
này có ý nghĩa quan trọng trong việc phân tích đặc điểm khách hàng và
xây dựng các chiến lược tiếp thị phù hợp.#Lập bảng tần số
ms_table<- table(dt1$MaritalStatus)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
MS <- table(dt1$MaritalStatus)/sum(nrow(dt1))
MS
##
## M S
## 0.4883704 0.5116296
# Cài đặt và nạp gói ggplot2 nếu chưa có
library(ggplot2)
# Tạo bảng dữ liệu từ biến Gender
ms_df <- as.data.frame(table(dt1$MaritalStatus))
colnames(ms_df) <- c("MaritalStatus", "Count")
# Tính phần trăm
ms_df$Percent <- round(ms_df$Count / sum(ms_df$Count) * 100, 1)
ms_df$Label <- paste0(ms_df$MaritalStatus, " (", ms_df$Percent, "%)")
# Vẽ biểu đồ tròn
ggplot(ms_df, aes(x = "", y = Count, fill = MaritalStatus)) +
geom_bar(width = 1, stat = "identity", color = "white") +
coord_polar("y", start = 0) +
geom_text(aes(label = Label), position = position_stack(vjust = 0.5), size = 5) +
labs(title = "BIEU DO TINH TRANG HON NHAN") +
scale_fill_manual(values = c("pink", "lightblue")) +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14))
Homeowner cho biết tình trạng sở hữu nhà của khách
hàng, bao gồm hai giá trị: “Y” (Yes – có sở hữu nhà) và “N” (No – không
sở hữu nhà). Đây là một biến phân loại định tính, phản ánh mức độ ổn
định về tài chính và nơi ở của khách hàng. Việc sở hữu nhà có thể liên
quan đến thu nhập, độ tuổi hoặc giai đoạn cuộc sống, từ đó ảnh hưởng đến
nhu cầu và hành vi mua sắm. Do đó, biến này có thể đóng vai trò quan
trọng trong việc phân khúc khách hàng và phân tích khả năng chi tiêu
hoặc xu hướng tiêu dùng của họ.#Lập bảng tần số
ho_table<- table(dt1$Homeowner)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
HO <- table(dt1$Homeowner)/sum(nrow(dt1))
HO
##
## N Y
## 0.3993883 0.6006117
library(ggplot2)
# Tính tỷ lệ phần trăm
homeowner_df <- as.data.frame(table(dt1$Homeowner))
colnames(homeowner_df) <- c("Homeowner", "Count")
homeowner_df$Percent <- homeowner_df$Count / sum(homeowner_df$Count) * 100
# Vẽ biểu đồ cột theo phần trăm
ggplot(homeowner_df, aes(x = Homeowner, y = Percent, fill = Homeowner)) +
geom_bar(stat = "identity", width = 0.6) +
scale_fill_manual(values = c("Y" = "#4CAF50", "N" = "#F44336")) +
labs(
title = "Bieu Do Tinh Trang So Huu Nha",
x = "Ty le so huu nha",
y = "(%)"
) +
theme_minimal(base_size = 14) +
theme(legend.position = "none") +
geom_text(aes(label = paste0(round(Percent, 1), "%")), vjust = -0.5, size = 5)
Biến Homeowner là một biến định tính nhị phân, phản ánh tình trạng sở hữu nhà ở của khách hàng. Biến này bao gồm hai giá trị: “Y” (Yes) – khách hàng có sở hữu nhà, và “N” (No) – khách hàng không sở hữu nhà. Việc sở hữu nhà có thể phản ánh mức độ ổn định tài chính cũng như năng lực chi tiêu của người tiêu dùng.
Sau khi tính toán tỷ lệ phần trăm các nhóm, kết quả cho thấy: 60.06% khách hàng thuộc nhóm có nhà ở riêng, trong khi 39.94% khách hàng không sở hữu nhà.
Điều này cho thấy phần lớn khách hàng trong tập dữ liệu là những người có mức độ ổn định nhất định về kinh tế. Đây có thể là một yếu tố quan trọng ảnh hưởng đến hành vi mua sắm, vì những người có nhà có xu hướng đầu tư hoặc chi tiêu cho gia đình nhiều hơn. Ngược lại, nhóm không sở hữu nhà có thể có xu hướng chi tiêu tiết kiệm hoặc chọn các sản phẩm thiết yếu hơn.
Biến City trong bộ dữ liệu biểu thị
thành phố nơi diễn ra giao dịch mua hàng. Đây là một
biến định tính (categorical variable) với nhiều giá trị như Los
Angeles, Bremerton, Portland, Salem, Tacoma, v.v… Biến này giúp xác
định phân bố địa lý của các giao dịch trong tập dữ liệu, từ đó có thể
phân tích thói quen tiêu dùng theo khu vực, xác định thị trường trọng
điểm hoặc xu hướng mua sắm theo vùng.
Ví dụ, các thành phố có tỷ lệ giao dịch cao nhất là:
Những thông tin này có thể giúp doanh nghiệp tập trung chiến lược tiếp thị, phân bổ nguồn lực hoặc đánh giá hiệu quả kinh doanh theo khu vực địa lý cụ thể.
#Lập bảng tần số
tp_table<- table(dt1$City)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
tp <- table(dt1$City)/sum(nrow(dt1))
tp
##
## Acapulco Bellingham Beverly Hills Bremerton Camacho
## 0.027242336 0.010171420 0.057685468 0.059321431 0.032150224
## Guadalajara Hidalgo Los Angeles Merida Mexico City
## 0.005334661 0.060103848 0.065865282 0.046518245 0.013798990
## Orizaba Portland Salem San Andres San Diego
## 0.033003770 0.062308841 0.098584537 0.044170994 0.061597553
## San Francisco Seattle Spokane Tacoma Vancouver
## 0.009246746 0.065580767 0.062237712 0.089408920 0.045024539
## Victoria Walla Walla Yakima
## 0.012518671 0.011380610 0.026744434
library(ggplot2)
cities <- c("Acapulco", "Bellingham", "Beverly Hills", "Bremerton", "Camacho", "Guadalajara", "Hidalgo", "Los Angeles", "Merida",
"Mexico City", "Orizaba", "Portland", "Salem", "San Andres", "San Diego", "San Francisco", "Seattle", "Spokane",
"Tacoma", "Vancouver", "Victoria", "Walla Walla", "Yakima")
values <- c(0.027242336, 0.010171420, 0.057685468, 0.059321431, 0.032150224, 0.005334661, 0.060103848, 0.065865282, 0.046518245,
0.013798990, 0.033003770, 0.062308841, 0.098584537, 0.044170994, 0.061597553, 0.009246746, 0.065580767, 0.062237712,
0.089408920, 0.045024539, 0.012518671, 0.011380610, 0.026744434)
df <- data.frame(City = factor(cities, levels = rev(cities)), Value = values)
ggplot(df, aes(x = City, y = Value)) +
geom_bar(stat = "identity", fill = "steelblue") +
coord_flip() +
theme_minimal() +
labs(title = "Biểu đồ % giao dịch theo TP", x = "TP", y = "Giá trị")
Biểu đồ thể hiện giá trị (có thể là tỉ lệ, điểm số hay số liệu đo lường nào đó) tương ứng với từng thành phố trong danh sách. Việc sử dụng biểu đồ cột ngang giúp dễ dàng quan sát và so sánh giá trị giữa các thành phố, đồng thời tên thành phố được trình bày rõ ràng, không bị chồng chéo hay khó đọc.
Từ biểu đồ, có thể rút ra một số điểm chính như sau:
Việc phân bố giá trị như trên có thể phản ánh các đặc điểm riêng biệt của từng thành phố theo biến bạn đang đo. Ví dụ, nếu đây là tỉ lệ dân số, mật độ, hoặc mức độ phát triển kinh tế, thì các thành phố lớn hoặc trung tâm khu vực có thể có giá trị cao hơn.
Biểu đồ giúp người xem dễ dàng phát hiện các thành phố có giá trị nổi bật, cũng như nhóm các thành phố có mức giá trị tương đương nhau. Từ đó, có thể làm cơ sở để phân tích sâu hơn về nguyên nhân, yếu tố ảnh hưởng, hoặc để đề xuất các giải pháp, chiến lược phù hợp.
Biến StateorProvince biểu thị mã viết tắt của bang
hoặc tỉnh mà mỗi thành phố thuộc về trong tập dữ liệu. Cụ thể, các mã
"CA", "WA", và "OR" lần lượt đại
diện cho các bang California, Washington và Oregon tại Hoa Kỳ. Biến này
giúp phân loại các thành phố theo khu vực địa lý rộng hơn, tạo điều kiện
thuận lợi cho việc phân tích và so sánh dữ liệu giữa các vùng lãnh thổ
khác nhau. Thông qua biến này, chúng ta có thể nhận diện được sự khác
biệt hoặc xu hướng đặc trưng của các thành phố dựa trên vị trí hành
chính của chúng, từ đó hỗ trợ các phân tích sâu hơn về mặt địa lý hoặc
chính sách.
#Lập bảng tần số
sp_table<- table(dt1$StateorProvince)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
sp <- table(dt1$StateorProvince)/sum(nrow(dt1))
sp
##
## BC CA DF Guerrero Jalisco OR
## 0.057543211 0.194395049 0.057969984 0.027242336 0.005334661 0.160893378
## Veracruz WA Yucatan Zacatecas
## 0.033003770 0.324845295 0.046518245 0.092254072
library(ggplot2)
# Dữ liệu
regions <- c("BC", "CA", "DF", "Guerrero", "Jalisco", "OR", "Veracruz", "WA", "Yucatan", "Zacatecas")
values <- c(0.057543211, 0.194395049, 0.057969984, 0.027242336, 0.005334661, 0.160893378, 0.033003770, 0.324845295, 0.046518245, 0.092254072)
df <- data.frame(Region = factor(regions, levels = rev(regions)), Value = values)
# Vẽ biểu đồ cột ngang
ggplot(df, aes(x = Region, y = Value)) +
geom_bar(stat = "identity", fill = "darkorange") +
coord_flip() +
theme_minimal() +
labs(title = "Biểu Đồ % Giao Dịch Theo Bang", x = "Bang", y = "%")
Biến StateorProvince đại diện cho tên viết tắt của các bang hoặc tỉnh mà từng thành phố trong tập dữ liệu thuộc về. Các giá trị trong biến bao gồm cả khu vực của Hoa Kỳ (như California – CA, Oregon – OR, Washington – WA) và các bang của Mexico (như Baja California – BC, Distrito Federal – DF, Guerrero, Jalisco, Veracruz, Yucatan, Zacatecas). Mỗi khu vực được gắn với một giá trị cụ thể, phản ánh mức độ của một đặc điểm nào đó, có thể là chỉ số kinh tế, tỷ lệ dân số, mức độ phát triển, hoặc một yếu tố đo lường xã hội khác.
Biểu đồ cột ngang trực quan hóa biến này cho thấy sự khác biệt rõ rệt giữa các vùng. Bang Washington (WA) có giá trị cao nhất (xấp xỉ 0.325), tiếp theo là California (CA) và Oregon (OR) với các giá trị lần lượt khoảng 0.194 và 0.161. Ngược lại, một số bang của Mexico như Jalisco và Guerrero có giá trị thấp hơn đáng kể, dưới 0.03. Điều này cho thấy sự phân hóa về đặc điểm được đo lường giữa các vùng lãnh thổ.
Việc sử dụng biểu đồ cột ngang giúp làm nổi bật sự chênh lệch giữa các khu vực, đồng thời cho phép so sánh dễ dàng hơn. Biến StateOrProvince đóng vai trò quan trọng trong việc phân nhóm dữ liệu theo đơn vị hành chính lớn, hỗ trợ phân tích theo chiều không gian (địa lý) và giúp đưa ra nhận định hoặc giải thích về những khác biệt khu vực trong bộ dữ liệu.
Biến này đại diện cho quốc gia mà mỗi thành phố trong tập dữ liệu thuộc về, gồm ba giá trị: Canada, Mexico và USA. Mỗi quốc gia được gắn với một giá trị tổng hợp hoặc trung bình (ví dụ: tỷ lệ, chỉ số, hay mức độ đo lường nào đó). Cụ thể, Hoa Kỳ (USA) chiếm tỷ trọng lớn nhất với giá trị 0.6801, tiếp theo là Mexico với 0.2623, và Canada có giá trị thấp nhất là 0.0575.
Sự phân bố này cho thấy phần lớn dữ liệu (hoặc giá trị đo lường) tập trung ở Hoa Kỳ, phản ánh có thể là do số lượng thành phố thuộc USA nhiều hơn, hoặc mức độ phát triển, dân số, hay một chỉ số liên quan nào đó cao hơn so với hai quốc gia còn lại. Mexico tuy thấp hơn USA nhưng vẫn chiếm tỷ trọng tương đối đáng kể, trong khi Canada có giá trị nhỏ nhất, cho thấy mức độ xuất hiện hoặc đặc điểm đo lường ở đây khá hạn chế trong tập dữ liệu.
Biến Country giúp nhóm dữ liệu theo quốc gia, phục vụ các phân tích theo cấp độ vùng quốc tế, đồng thời hỗ trợ đánh giá và so sánh giữa các quốc gia về đặc điểm đang được quan tâm.
#Lập bảng tần số
country_table<- table(dt1$Country)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
country <- table(dt1$Country)/sum(nrow(dt1))
country
##
## Canada Mexico USA
## 0.05754321 0.26232307 0.68013372
library(ggplot2)
# Dữ liệu
countries <- c("Canada", "Mexico", "USA")
values <- c(0.05754321, 0.26232307, 0.68013372)
df <- data.frame(Country = countries, Value = values)
# Tính phần trăm và nhãn hiển thị
df$Percentage <- paste0(round(df$Value * 100, 1), "%")
# Vẽ biểu đồ tròn
ggplot(df, aes(x = "", y = Value, fill = Country)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y") +
theme_void() +
geom_text(aes(label = Percentage),
position = position_stack(vjust = 0.5),
color = "white", size = 5) +
labs(title = "Tỷ trọng theo quốc gia") +
scale_fill_brewer(palette = "Set2")
Biểu đồ tròn thể hiện sự phân bố giá trị của biến theo ba quốc gia: Canada, Mexico, và Hoa Kỳ (USA). Kết quả cho thấy có sự chênh lệch đáng kể giữa các quốc gia về tỷ trọng đóng góp vào tổng giá trị của biến được phân tích. Cụ thể, Hoa Kỳ chiếm tỷ lệ áp đảo với khoảng 68% tổng giá trị, trong khi Mexico chiếm khoảng 26% và Canada chỉ đóng góp khoảng 6%.
Tỷ trọng cao của Hoa Kỳ có thể phản ánh một số yếu tố: (1) số lượng thành phố hoặc điểm dữ liệu thuộc Hoa Kỳ trong tập dữ liệu có thể lớn hơn đáng kể so với hai quốc gia còn lại; (2) bản thân các giá trị được đo lường (ví dụ: chỉ số phát triển, mức độ tiêu thụ, hoặc bất kỳ biến đặc trưng nào) ở các thành phố của Hoa Kỳ có xu hướng cao hơn; hoặc (3) kết hợp cả hai yếu tố nêu trên. Trong khi đó, tỷ trọng thấp của Canada cho thấy mức độ hiện diện của quốc gia này trong bộ dữ liệu là khá khiêm tốn, cả về số lượng quan sát và/hoặc giá trị của biến được đo.
Việc sử dụng biểu đồ tròn trong trường hợp này giúp người đọc nhanh chóng hình dung được cơ cấu phân bố giữa các nhóm quốc gia, đồng thời nhấn mạnh sự khác biệt rõ rệt về tỷ trọng đóng góp. Đây là bước quan trọng trong việc khám phá dữ liệu ban đầu (exploratory data analysis), nhằm cung cấp bối cảnh và định hướng cho các phân tích sâu hơn ở cấp độ vùng lãnh thổ. Biểu đồ cũng đóng vai trò làm nổi bật đặc điểm cấu trúc của dữ liệu, giúp người làm phân tích đưa ra các giả định hợp lý cho mô hình thống kê hoặc giải thích kết quả về sau.
#Lập bảng tần số
pf_table<- table(dt1$ProductFamily)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
pf <- table(dt1$ProductFamily)/sum(nrow(dt1))
pf
##
## Drink Food Non-Consumable
## 0.08891102 0.72217085 0.18891813
library(ggplot2)
# Dữ liệu
product_family <- c("Drink", "Food", "Non-Consumable")
values <- c(0.08891102, 0.72217085, 0.18891813)
df <- data.frame(ProductFamily = product_family, Value = values)
# Tính phần trăm và tạo nhãn
df$Percentage <- paste0(round(df$Value * 100, 1), "%")
# Vẽ biểu đồ tròn đẹp mắt
ggplot(df, aes(x = "", y = Value, fill = ProductFamily)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y") +
theme_void() +
geom_text(aes(label = Percentage),
position = position_stack(vjust = 0.5),
color = "white", size = 6, fontface = "bold") +
labs(title = " Cac Nhom SP Trong ProductFamily") +
scale_fill_manual(values = c("#6baed6", "#31a354", "#de2d26")) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
legend.title = element_blank(),
legend.text = element_text(size = 12)
)
Kết luận từ phân tích biến ProductFamily cho thấy rõ ràng rằng nhóm Thực phẩm (Food) chiếm tỷ trọng áp đảo trong tập dữ liệu, với khoảng 72%, cho thấy đây là nhóm sản phẩm chủ lực và đóng vai trò then chốt trong hoạt động kinh doanh hoặc khảo sát được thực hiện. Việc chiếm ưu thế của nhóm thực phẩm phản ánh nhu cầu thiết yếu và liên tục của người tiêu dùng đối với các mặt hàng này, đồng thời cho thấy trọng tâm của thị trường hoặc nghiên cứu nằm nhiều ở lĩnh vực này.
Nhóm Hàng không tiêu dùng (Non-Consumable), mặc dù chỉ chiếm khoảng 19%, vẫn đóng vai trò quan trọng như một phần bổ sung, đáp ứng các nhu cầu về sản phẩm bền lâu hoặc không tiêu thụ nhanh. Trong khi đó, nhóm Đồ uống (Drink) với tỷ lệ khoảng 9% tuy nhỏ hơn nhiều so với thực phẩm, nhưng vẫn góp phần đa dạng hóa danh mục sản phẩm và đáp ứng nhu cầu tiêu dùng hàng ngày của khách hàng.
Hiểu rõ cơ cấu phân bổ các nhóm sản phẩm này không chỉ giúp doanh nghiệp hoặc nhà nghiên cứu nắm bắt được bức tranh tổng thể của thị trường mà còn cung cấp cơ sở để định hướng chiến lược phát triển sản phẩm, phân bổ nguồn lực hợp lý và tối ưu hóa kế hoạch tiếp thị. Việc tập trung vào nhóm thực phẩm cũng gợi ý rằng các chính sách và chiến dịch nên được ưu tiên phát triển nhằm củng cố và mở rộng thị phần trong lĩnh vực này, đồng thời khám phá cơ hội tăng trưởng tiềm năng ở các nhóm sản phẩm khác để đa dạng hóa và giảm thiểu rủi ro.
#Lập bảng tần số
pd_table<- table(dt1$ProductDepartment)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
pd <- table(dt1$ProductDepartment)/sum(nrow(dt1))
pd
##
## Alcoholic Beverages Baked Goods Baking Goods Beverages
## 0.025321858 0.030229746 0.076250089 0.048367594
## Breakfast Foods Canned Foods Canned Products Carousel
## 0.013372217 0.069492852 0.007753041 0.004196600
## Checkout Dairy Deli Eggs
## 0.005832563 0.064229319 0.049719041 0.014083505
## Frozen Foods Health and Hygiene Household Meat
## 0.098300021 0.063518031 0.101002916 0.006330464
## Periodicals Produce Seafood Snack Foods
## 0.014368020 0.141830856 0.007255139 0.113806103
## Snacks Starchy Foods
## 0.025037343 0.019702682
Biến ProductCategory phản ánh các loại sản phẩm cụ thể thuộc các nhóm hàng khác nhau trong tập dữ liệu. Dữ liệu cho thấy sự đa dạng phong phú với nhiều loại mặt hàng như Frozen Foods (Thực phẩm đông lạnh) chiếm tỷ lệ cao nhất khoảng 9.8%, tiếp theo là Produce (Rau củ quả tươi) với gần 14.2%, và các nhóm khác như Household (Đồ gia dụng) chiếm khoảng 10.1%, Snack Foods (Đồ ăn nhẹ) khoảng 11.4%. Các nhóm còn lại như Baking Goods (Nguyên liệu làm bánh), Dairy (Sản phẩm từ sữa), và Beverages (Đồ uống) cũng góp phần tạo nên cấu trúc đa dạng và cân bằng cho danh mục sản phẩm, dù tỷ lệ thấp hơn.
Sự phân bổ tỷ lệ này phản ánh thị trường rộng lớn và đa dạng của các loại sản phẩm tiêu dùng, từ các mặt hàng thiết yếu như rau củ, thực phẩm đông lạnh, đến các mặt hàng phụ trợ như đồ gia dụng và sản phẩm vệ sinh cá nhân. Việc hiểu rõ cơ cấu này giúp doanh nghiệp và các nhà quản lý dễ dàng xây dựng chiến lược phát triển sản phẩm phù hợp, đồng thời nắm bắt được nhu cầu thị trường ở nhiều phân khúc khác nhau nhằm tối ưu hóa nguồn lực và hiệu quả kinh doanh.
library(ggplot2)
# Dữ liệu
categories <- c("Alcoholic Beverages", "Baked Goods", "Baking Goods", "Beverages",
"Breakfast Foods", "Canned Foods", "Canned Products", "Carousel",
"Checkout", "Dairy", "Deli", "Eggs", "Frozen Foods", "Health and Hygiene",
"Household", "Meat", "Periodicals", "Produce", "Seafood", "Snack Foods",
"Snacks", "Starchy Foods")
values <- c(0.025321858, 0.030229746, 0.076250089, 0.048367594,
0.013372217, 0.069492852, 0.007753041, 0.004196600,
0.005832563, 0.064229319, 0.049719041, 0.014083505,
0.098300021, 0.063518031, 0.101002916, 0.006330464,
0.014368020, 0.141830856, 0.007255139, 0.113806103,
0.025037343, 0.019702682)
df <- data.frame(Category = categories, Value = values)
# Sắp xếp theo giá trị giảm dần để biểu đồ trực quan hơn
df <- df[order(df$Value, decreasing = TRUE), ]
df$Category <- factor(df$Category, levels = df$Category)
# Vẽ biểu đồ cột ngang
ggplot(df, aes(x = Category, y = Value, fill = Value)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_gradient(low = "#aec7e8", high = "#1f77b4") +
theme_minimal() +
labs(title = "% Nhom SP Trong ProductCategory",
x = "Nhom SP",
y = "Tỷ lệ") +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 16),
axis.text = element_text(size = 11),
axis.title = element_text(size = 13)
)
Phân tích biến ProductCategory cho thấy sự phân bố đa dạng và phong phú của các nhóm sản phẩm trong tập dữ liệu, phản ánh bức tranh toàn diện về danh mục hàng hóa tiêu dùng. Các nhóm sản phẩm như Produce (Rau củ tươi), Household (Đồ gia dụng) và Frozen Foods (Thực phẩm đông lạnh) chiếm tỷ lệ cao nhất, lần lượt khoảng 14.2%, 10.1% và 9.8%. Điều này cho thấy thị trường tập trung mạnh vào các mặt hàng thiết yếu, phục vụ nhu cầu hàng ngày của người tiêu dùng. Bên cạnh đó, các nhóm như Snack Foods (Đồ ăn nhẹ), Baking Goods (Nguyên liệu làm bánh) và Dairy (Sản phẩm từ sữa) cũng có sự đóng góp đáng kể, làm tăng sự đa dạng trong danh mục sản phẩm.
Kết quả này không chỉ giúp nhận diện các nhóm sản phẩm chủ lực mà còn cung cấp thông tin quan trọng để các nhà quản lý và nhà hoạch định chiến lược có thể tập trung phát triển, phân bổ nguồn lực hợp lý, đồng thời mở rộng hoặc cải tiến các nhóm sản phẩm nhằm đáp ứng tốt hơn nhu cầu thị trường. Sự đa dạng này cũng phản ánh tính cạnh tranh và khả năng thích ứng của doanh nghiệp trong môi trường kinh doanh ngày càng biến động.
#Lập bảng tần số
pc_table<- table(dt1$ProductCategory)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
pc <- table(dt1$ProductCategory)/sum(nrow(dt1))
pc
##
## Baking Goods Bathroom Products Beer and Wine
## 0.034426346 0.025962017 0.025321858
## Bread Breakfast Foods Candles
## 0.030229746 0.029660716 0.003200797
## Candy Canned Anchovies Canned Clams
## 0.025037343 0.003129668 0.003769827
## Canned Oysters Canned Sardines Canned Shrimp
## 0.002489508 0.002845153 0.002702895
## Canned Soup Canned Tuna Carbonated Beverages
## 0.028736041 0.006188207 0.010953837
## Cleaning Supplies Cold Remedies Dairy
## 0.013443346 0.006614980 0.064229319
## Decongestants Drinks Eggs
## 0.006045949 0.009602390 0.014083505
## Electrical Frozen Desserts Frozen Entrees
## 0.025250729 0.022974607 0.008393200
## Fruit Hardware Hot Beverages
## 0.054413543 0.009175617 0.016075112
## Hygiene Jams and Jellies Kitchen Products
## 0.014012376 0.041823743 0.015434953
## Magazines Meat Miscellaneous
## 0.014368020 0.054129028 0.002987410
## Packaged Vegetables Pain Relievers Paper Products
## 0.003414183 0.013656732 0.024539441
## Pizza Plastic Products Pure Juice Beverages
## 0.013798990 0.010029163 0.011736254
## Seafood Side Dishes Snack Foods
## 0.007255139 0.010882709 0.113806103
## Specialty Starchy Foods Vegetables
## 0.020556227 0.019702682 0.122910591
Biến ProductSubCategory cung cấp cái nhìn sâu sắc và toàn diện về sự đa dạng trong danh mục sản phẩm tiêu dùng, phân loại các mặt hàng theo các nhóm chi tiết và đặc trưng riêng biệt. Dữ liệu cho thấy các nhóm thực phẩm như Vegetables (Rau củ tươi) và Snack Foods (Đồ ăn nhẹ) chiếm tỷ lệ đáng kể, lần lượt khoảng 12.3% và 11.4%, phản ánh nhu cầu mạnh mẽ và sự ưa chuộng của người tiêu dùng đối với các mặt hàng tươi ngon, tiện lợi và dễ sử dụng hàng ngày. Bên cạnh đó, các nhóm như Fruit (Trái cây) và Meat (Thịt) cũng góp phần quan trọng trong việc hoàn thiện cấu trúc thực phẩm, nhấn mạnh tính đa dạng và phong phú của các sản phẩm tươi sống.
Không chỉ giới hạn ở thực phẩm, biến này còn thể hiện vai trò không thể thiếu của các nhóm sản phẩm gia dụng và hỗ trợ như Cleaning Supplies (Vật dụng làm sạch), Paper Products (Sản phẩm giấy), và Bathroom Products (Đồ dùng phòng tắm), mặc dù chiếm tỷ lệ nhỏ hơn nhưng góp phần nâng cao trải nghiệm tiêu dùng toàn diện và đáp ứng nhu cầu thiết yếu trong cuộc sống hàng ngày. Sự cân bằng và đa dạng giữa các nhóm sản phẩm này không chỉ phản ánh rõ nét xu hướng tiêu dùng hiện đại mà còn giúp doanh nghiệp có định hướng phát triển sản phẩm, tối ưu hóa danh mục hàng hóa và khai thác hiệu quả thị trường mục tiêu.
library(ggplot2)
# Dữ liệu (giữ nguyên như trước)
sub_categories <- c("Baking Goods", "Bathroom Products", "Beer and Wine", "Bread", "Breakfast Foods", "Candles",
"Candy", "Canned Anchovies", "Canned Clams", "Canned Oysters", "Canned Sardines", "Canned Shrimp",
"Canned Soup", "Canned Tuna", "Carbonated Beverages", "Cleaning Supplies", "Cold Remedies", "Dairy",
"Decongestants", "Drinks", "Eggs", "Electrical", "Frozen Desserts", "Frozen Entrees", "Fruit",
"Hardware", "Hot Beverages", "Hygiene", "Jams and Jellies", "Kitchen Products", "Magazines",
"Meat", "Miscellaneous", "Packaged Vegetables", "Pain Relievers", "Paper Products", "Pizza",
"Plastic Products", "Pure Juice Beverages", "Seafood", "Side Dishes", "Snack Foods", "Specialty",
"Starchy Foods", "Vegetables")
values <- c(0.034426346, 0.025962017, 0.025321858, 0.030229746, 0.029660716, 0.003200797,
0.025037343, 0.003129668, 0.003769827, 0.002489508, 0.002845153, 0.002702895,
0.028736041, 0.006188207, 0.010953837, 0.013443346, 0.006614980, 0.064229319,
0.006045949, 0.009602390, 0.014083505, 0.025250729, 0.022974607, 0.008393200, 0.054413543,
0.009175617, 0.016075112, 0.014012376, 0.041823743, 0.015434953, 0.014368020,
0.054129028, 0.002987410, 0.003414183, 0.013656732, 0.024539441, 0.013798990,
0.010029163, 0.011736254, 0.007255139, 0.010882709, 0.113806103, 0.020556227,
0.019702682, 0.122910591)
df <- data.frame(SubCategory = sub_categories, Value = values)
# Sắp xếp
df <- df[order(df$Value, decreasing = TRUE), ]
df$SubCategory <- factor(df$SubCategory, levels = df$SubCategory)
# Vẽ biểu đồ với màu gradient xanh lam sang xanh lá pastel
ggplot(df, aes(x = SubCategory, y = Value, fill = Value)) +
geom_bar(stat = "identity", color = "gray30", size = 0.3) + # viền bar nhẹ giúp sang hơn
coord_flip() +
scale_fill_gradient(low = "#a6cee3", high = "#1f78b4") + # xanh nhạt tới xanh đậm
theme_minimal(base_size = 14) +
labs(title = "% Nhom SP Trong ProductSubCategory",
x = "Nhom SP Chi Tiet",
y = "Tỷ lệ") +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 18, color = "#333333"),
axis.text = element_text(size = 11, color = "#555555"),
axis.title = element_text(size = 14),
legend.position = "none" # ẩn thanh legend vì màu biểu diễn tỷ lệ rất rõ rồi
)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Biến ProductSubCategory phản ánh sự đa dạng phong phú trong danh mục các mặt hàng tiêu dùng, từ thực phẩm tươi sống đến các sản phẩm gia dụng và đồ dùng hàng ngày. Qua biểu đồ trực quan, ta có thể nhận thấy rõ ràng một số nhóm sản phẩm chiếm tỷ trọng lớn nổi bật như Vegetables (Rau củ tươi) và Snack Foods (Đồ ăn nhẹ), lần lượt đạt khoảng 12.3% và 11.4% tổng sản phẩm. Điều này cho thấy xu hướng tiêu dùng hiện nay ưu tiên các mặt hàng tiện lợi, dễ sử dụng nhưng vẫn đảm bảo dinh dưỡng và độ tươi mới.
Bên cạnh đó, các nhóm thực phẩm khác như Fruit (Trái cây), Frozen Desserts (Kem đông lạnh) và Dairy (Sản phẩm từ sữa) cũng đóng vai trò quan trọng trong cơ cấu sản phẩm, thể hiện sự đa dạng và nhu cầu cao đối với các sản phẩm bổ dưỡng, phong phú về lựa chọn. Các nhóm sản phẩm gia dụng như Cleaning Supplies (Vật dụng làm sạch), Paper Products (Sản phẩm giấy) và Bathroom Products (Đồ dùng phòng tắm) mặc dù chiếm tỷ lệ nhỏ hơn, nhưng góp phần tạo nên sự hoàn thiện cho trải nghiệm mua sắm, đáp ứng các nhu cầu thiết yếu trong đời sống hàng ngày.
Nhìn chung, sự phân bố cân đối giữa các nhóm sản phẩm thực phẩm và gia dụng thể hiện chiến lược đa dạng hóa danh mục hàng hóa nhằm phục vụ tốt hơn cho khách hàng với các lựa chọn phong phú, phù hợp nhiều mục đích tiêu dùng khác nhau. Đây là điểm mạnh giúp doanh nghiệp dễ dàng tiếp cận và mở rộng thị trường, đồng thời duy trì tính cạnh tranh bền vững trong ngành hàng tiêu dùng.
#Lập bảng tần số
ai_table<- table(dt1$AnnualIncome)
#Tính toán tỷ lệ phần trăm mỗi hạng mục
ai <- table(dt1$AnnualIncome)/sum(nrow(dt1))
ai
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 0.21978804 0.04573583 0.05405790 0.01941817 0.32726367
## $50K - $70K $70K - $90K $90K - $110K
## 0.16857529 0.12155914 0.04360196
library(ggplot2)
# Dữ liệu
income_levels <- c("$10K - $30K", "$110K - $130K", "$130K - $150K", "$150K +",
"$30K - $50K", "$50K - $70K", "$70K - $90K", "$90K - $110K")
values <- c(0.21978804, 0.04573583, 0.05405790, 0.01941817,
0.32726367, 0.16857529, 0.12155914, 0.04360196)
df_income <- data.frame(Income = income_levels, Proportion = values)
# Sắp xếp theo thứ tự thu nhập tăng dần (để biểu đồ dễ hiểu)
order_levels <- c("$10K - $30K", "$30K - $50K", "$50K - $70K", "$70K - $90K",
"$90K - $110K", "$110K - $130K", "$130K - $150K", "$150K +")
df_income$Income <- factor(df_income$Income, levels = order_levels)
# Vẽ biểu đồ cột
ggplot(df_income, aes(x = Income, y = Proportion, fill = Proportion)) +
geom_bar(stat = "identity", color = "gray30", size = 0.3) +
scale_fill_gradient(low = "#b2df8a", high = "#33a02c") + # xanh lá pastel đến xanh đậm
theme_minimal(base_size = 14) +
labs(title = "Bieu Do % Theo Khoang Thu Nhap",
x = "Khoang Thu Nhap Hang Nam",
y = "Tỷ lệ") +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 18, color = "#333333"),
axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 14),
legend.position = "none"
)
Biến AnnualIncome cung cấp cái nhìn rõ nét về phân bố thu nhập hàng năm của đối tượng trong mẫu dữ liệu, phản ánh đa dạng mức thu nhập từ thấp đến cao. Qua biểu đồ, ta thấy nhóm thu nhập phổ biến nhất là khoảng “$30K - $50K”, chiếm gần một phần ba tổng số, cho thấy phần lớn đối tượng thuộc tầng lớp trung bình. Các nhóm thu nhập thấp hơn như “$10K - $30K” cũng chiếm tỷ lệ đáng kể, cho thấy vẫn còn một bộ phận người tiêu dùng có thu nhập hạn chế. Trong khi đó, các nhóm thu nhập cao trên “$90K” chiếm tỷ lệ nhỏ hơn, cho thấy thị trường này có sự phân hóa rõ rệt giữa các phân khúc tài chính.
Hiểu rõ sự phân bố thu nhập giúp doanh nghiệp và nhà nghiên cứu định hình các chiến lược tiếp thị và phát triển sản phẩm phù hợp với khả năng chi tiêu của từng nhóm khách hàng. Ví dụ, các chương trình khuyến mãi hoặc sản phẩm đặc thù có thể tập trung vào nhóm thu nhập trung bình – nhóm chiếm phần lớn trong dữ liệu. Đồng thời, việc nhận diện các nhóm thu nhập cao cũng mở ra cơ hội khai thác các sản phẩm cao cấp, đa dạng hóa danh mục nhằm đáp ứng nhu cầu khác biệt của khách hàng.
Tóm lại, biến AnnualIncome không chỉ phản ánh đặc điểm kinh tế của khách hàng mà còn là công cụ quan trọng trong phân tích thị trường và hoạch định chiến lược kinh doanh hiệu quả.
Ước lượng khoảng là phương pháp xác định một khoảng giá trị hợp lý cho tham số tổng thể dựa trên số liệu mẫu. Với tỷ lệ thành công p trong tổng thể, ta sử dụng tỷ lệ mẫu và sai số chuẩn để tính khoảng tin cậy.
Khoảng tin cậy 95% cho tỷ lệ được tính theo công thức:
\[ \hat{p} \pm z_{\alpha/2} \cdot \sqrt{\frac{\hat{p}(1 - \hat{p})}{n}} \]
Giải thích từng thành phần:
\(\hat{p}\): ước lượng tỷ lệ từ mẫu.
\(z_{\alpha/2}\): giá trị tới hạn từ phân phối chuẩn chuẩn hóa (Z), tương ứng với mức ý nghĩa \(\alpha\). Ví dụ, với khoảng tin cậy 95% thì \(z_{\alpha/2} \approx 1.96\).
\(\sqrt{\frac{\hat{p}(1 - \hat{p})}{n}}\): sai số chuẩn (standard error) của \(\hat{p}\).
Kiểm định giả thuyết là phương pháp thống kê nhằm kiểm tra xem giả thuyết về tham số tổng thể có phù hợp với dữ liệu quan sát hay không.
Trong trường hợp kiểm định tỷ lệ, ta muốn kiểm tra giá trị thực của tỷ lệ thành công \(p\) trong tổng thể.
Giả thuyết thống kê
Giả thuyết không (Null hypothesis, \(H_0\)): Tỷ lệ tổng thể bằng một
giá trị cụ thể \(p_0\), tức là
\[
H_0: p = p_0
\]
Giả thuyết đối (Alternative hypothesis, \(H_1\)) có thể là:
Thống kê kiểm định
Thống kê kiểm định dựa trên tỷ lệ mẫu \(\hat{p} = \frac{x}{n}\), trong đó:
- \(x\) là số thành công trong
mẫu
- \(n\) là kích thước mẫu
Công thức thống kê kiểm định \(Z\) là:
\[ Z = \frac{\hat{p} - p_0}{\sqrt{\frac{p_0(1-p_0)}{n}}} \]
Phân phối của \(Z\) theo phân phối chuẩn chuẩn hóa dưới giả thuyết \(H_0\).
Trong R, ta sử dụng hàm prop.test() để thực hiện kiểm
định tỷ lệ một mẫu.
| Tham số | Ý nghĩa |
|---|---|
x |
Số thành công trong mẫu |
n |
Kích thước mẫu |
p |
Giá trị tỷ lệ giả định trong giả thuyết không |
alternative |
Kiểu kiểm định: "two.sided", "less",
"greater" |
conf.level |
Mức độ tin cậy cho khoảng tin cậy (mặc định 0.95) |
Giả sử:
Khi đó, khoảng tin cậy \(100(1 - \alpha)\%\) cho tỷ lệ \(p\) được tính bằng công thức:
\[ \hat{p} \pm z_{\alpha/2} \cdot \sqrt{ \frac{ \hat{p}(1 - \hat{p}) }{n} } \]
Tức là:
\[ \left[ \hat{p} - z_{\alpha/2} \cdot \sqrt{ \frac{ \hat{p}(1 - \hat{p}) }{n} }, \quad \hat{p} + z_{\alpha/2} \cdot \sqrt{ \frac{ \hat{p}(1 - \hat{p}) }{n} } \right] \]
Trong đó:
| Kiểu kiểm định | Giả thuyết không \(H_0\) | Giả thuyết đối \(H_a\) | Ý nghĩa kinh tế lượng |
|---|---|---|---|
| Hai phía (Two-sided) | \(p = p_0\) | \(p \neq p_0\) | Kiểm tra tỷ lệ quan sát có khác biệt so với \(p_0\) |
| Một phía (trái) | \(p = p_0\) | \(p < p_0\) | Tỷ lệ quan sát có nhỏ hơn đáng kể so với \(p_0\) |
| Một phía (phải) | \(p = p_0\) | \(p > p_0\) | Tỷ lệ quan sát có lớn hơn đáng kể so với \(p_0\) |
Kết luận kiểm định
Nếu giá trị \(p\)-value \(< \alpha\) (thường \(\alpha = 0.05\)), ta bác bỏ giả thuyết không \(H_0\), nghĩa là có bằng chứng thống kê cho thấy tỷ lệ thực sự khác \(p_0\).
Nếu \(p\)-value \(\geq \alpha\), ta không bác bỏ \(H_0\), tức là không đủ bằng chứng để khẳng định tỷ lệ khác \(p_0\).
Biến ProductFamily phân loại sản phẩm thành ba nhóm
chính: Drink, Food, và Non-Consumable. Trong
phân tích này, chúng ta chọn “Food” làm hạng mục quan
tâm vì đây là nhóm sản phẩm có tỷ lệ cao nhất trong tập dữ liệu.
prop1.interval <- function(x, n, conf.level) {
p <- x / n
z.crit <- -1 * qnorm((1 - conf.level) / 2)
margin.error <- z.crit * sqrt(p * (1 - p) / n)
ci.lower <- p - margin.error
ci.upper <- p + margin.error
dat <- c(p, z.crit, margin.error, ci.lower, ci.upper)
names(dat) <- c("Ty le mau", "GTTH", "Bien Sai So", "Can duoi", "Can tren")
return(dat)
}
# Số lượng sản phẩm thuộc nhóm "Food"
xFood <- sum(dt1$ProductFamily == "Food")
# Ước lượng khoảng tin cậy 95%
prop1.interval(xFood,nrow(dt1),0.95)
## Ty le mau GTTH Bien Sai So Can duoi Can tren
## 0.722170851 1.959963985 0.007404228 0.714766624 0.729575079
Sử dụng công thức khoảng tin cậy:
\[ \hat{p} \pm z_{\alpha/2} \cdot \sqrt{ \frac{ \hat{p}(1 - \hat{p}) }{n} } \]
Với \(z_{0.025} = 1.96\), ta có:
\[ 0.722 \pm 1.96 \cdot \sqrt{ \frac{0.722 \cdot (1 - 0.722)}{1000} } \approx [0.692, 0.751] \]
Từ kết quả ước lượng ta có:
\[ \hat{p} = 0.722, \quad z_{\alpha/2} = 1.96, \quad SE = 0.0074, \quad CI = [0.7148, \; 0.7296] \]
Diễn giải: Với độ tin cậy 95%, ta có thể khẳng định rằng tỷ lệ thực sự của sản phẩm thuộc nhóm Food trong tổng thể nằm trong khoảng từ 71.48% đến 72.96%. Điều này cho thấy nhóm “Food” chiếm ưu thế rõ rệt trong danh mục sản phẩm và là nhóm sản phẩm chủ lực trong tập dữ liệu.
Giả thuyết kiểm định:
Sử dụng hàm prop.test() trong R:
prop.test(x = 722, n = 1000, p = 0.7, alternative = "two.sided", conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: 722 out of 1000, null probability 0.7
## X-squared = 2.2012, df = 1, p-value = 0.1379
## alternative hypothesis: true p is not equal to 0.7
## 95 percent confidence interval:
## 0.6929096 0.7493607
## sample estimates:
## p
## 0.722
Kết quả hiển thị như sau:
- Giá trị p-value = 0.1379, lớn hơn mức ý nghĩa \(\alpha = 0.05\).
- Khoảng tin cậy 95% cho tỷ lệ thực sự \(p\) là \([0.6929,\;0.7494]\).
- Ước lượng tỷ lệ mẫu \(\hat{p} = 0.722\).
Kết luận
Vì \(\text{p-value} = 0.1379 >
0.05\), ta không bác bỏ giả thuyết không
\[
H_0: p = 0.7.
\]
Điều này cho thấy không có đủ bằng chứng thống kê để khẳng định rằng tỷ lệ sản phẩm “Food” trong tổng thể khác 70%.
Ngoài ra, khoảng tin cậy 95% \([0.6929,\;0.7494]\) bao gồm giá trị \(0.7\), càng củng cố kết luận rằng tỷ lệ thực sự có thể bằng 70%. Mặc dù tỷ lệ mẫu \(\hat{p} = 0.722\) có xu hướng nhỉnh hơn, song chênh lệch không đủ mạnh về mặt thống kê để bác bỏ \(H_0\).
Biến Gender phân loại sản phẩm thành hai nhóm chính:
Male và Female. Trong phân tích này, chúng ta chọn
Male làm hạng mục quan tâm .
prop1.interval1 <- function(x, n, conf.level) {
p <- x / n
z.crit <- -1 * qnorm((1 - conf.level) / 2)
margin.error <- z.crit * sqrt(p * (1 - p) / n)
ci.lower <- p - margin.error
ci.upper <- p + margin.error
dat <- c(p, z.crit, margin.error, ci.lower, ci.upper)
names(dat) <- c("Ty le mau", "GTTH", "Bien Sai So", "Can duoi", "Can tren")
return(dat)
}
# Số lượng Male
xGender <- sum(dt1$Gender == "M")
# Ước lượng khoảng tin cậy 95%
prop1.interval1(xGender,nrow(dt1),0.95)
## Ty le mau GTTH Bien Sai So Can duoi Can tren
## 0.490006402 1.959963985 0.008263311 0.481743090 0.498269713
Từ kết quả ước lượng ta có:
Từ kết quả:
| Tỷ lệ mẫu (\(\hat{p}\)) | Giá trị tới hạn (\(z_{0.025}\)) | Biên sai số (\(E\)) | Cận dưới | Cận trên |
|---|---|---|---|---|
| 0.4900 | 1.95996 | 0.00826 | 0.48174 | 0.49827 |
Kết luận: Tỷ lệ nam (\(p_{\text{Male}}\)) nằm dưới 50% với 95% độ tin cậy, tức là chúng ta có bằng chứng thống kê để khẳng định tỷ lệ nam không đạt một nửa dân số trong tổng thể.
\[ \begin{aligned} H_0:&\; p_{\text{Male}} = 0.5 \quad\text{(tỷ lệ nam bằng 50\%)}\\ H_a:&\; p_{\text{Male}} \neq 0.5 \quad\text{(tỷ lệ nam khác 50\%)}. \end{aligned} \]
# Số lượng quan sát nam
xMale <- sum(dt1$Gender == "M")
# Tổng số quan sát
nTotal <- nrow(dt1)
# Kiểm định tỉ lệ một mẫu
test_male <- prop.test(x = xMale,
n = nTotal,
p = 0.5,
alternative = "two.sided",
conf.level = 0.95)
test_male
##
## 1-sample proportions test with continuity correction
##
## data: xMale out of nTotal, 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.4817114 0.4983069
## sample estimates:
## p
## 0.4900064
Kết quả thu được:
Nhận xét
Vì \(p\text{-value} = 0.0182 < \alpha =
0.05\), ta bác bỏ giả thuyết không
\[
H_0: p = 0.5.
\]
Khoảng tin cậy 95% \([0.4817,\;0.4983]\) không bao gồm giá trị
\(0.5\), củng cố kết luận rằng tỷ lệ
nam trong tổng thể khác 50%.
Kết quả kiểm định và khoảng tin cậy cho thấy tỷ lệ “Male” thực sự nằm
trong khoảng
\[
[0.4817,\;0.4983],
\]
tức là dưới 50% với ý nghĩa thống kê ở mức \(\alpha = 0.05\). Điều này ngụ ý nhóm
“Female” chiếm ưu thế nhẹ trong tổng thể.
Biến AnnualIncome phân loại thu nhập hàng năm của đối
tượng thành các khoảng:
$10K - $30K, **$30K - $50K**,
$50K - $70K, $70K - $90K,
$90K - $110K, $110K - $130K,
$130K - $150K, và $150K +.
Trong phân tích này, chúng ta chọn
$30K - $50K làm hạng mục quan tâm vì đây
là nhóm thu nhập trung cấp, thường phản ánh mức chi tiêu tiêu chuẩn của
đa số khách hàng.
prop1.interval2 <- function(x, n, conf.level) {
p <- x / n
z.crit <- -1 * qnorm((1 - conf.level) / 2)
margin.error <- z.crit * sqrt(p * (1 - p) / n)
ci.lower <- p - margin.error
ci.upper <- p + margin.error
dat <- c(p, z.crit, margin.error, ci.lower, ci.upper)
names(dat) <- c("Ty le mau", "GTTH", "Bien Sai So", "Can duoi", "Can tren")
return(dat)
}
# Số lượng Male
xAI <- sum(dt1$AnnualIncome == "$30K - $50K")
# Ước lượng khoảng tin cậy 95%
prop1.interval2(xAI,nrow(dt1),0.95)
## Ty le mau GTTH Bien Sai So Can duoi Can tren
## 0.327263675 1.959963985 0.007756079 0.319507596 0.335019753
Từ kết quả:
Diễn giải: Với độ tin cậy 95%, chúng ta có thể khẳng định rằng tỷ lệ thực sự của nhóm thu nhập $30K–$50K trong tổng thể nằm trong khoảng 31.95% đến 33.50%. Khoảng tin cậy khá hẹp cho thấy ước lượng rất chính xác, phản ánh kích thước mẫu đủ lớn để thu được kết quả tin cậy.
Kiểm định giả thuyết cho nhóm thu nhập $30K - $50K
Giả thuyết kiểm định:
\[ \begin{aligned} H_0:&\; p = 0.33 \quad(\text{tỷ lệ nhóm \$30K–\$50K bằng 33\%})\\ H_a:&\; p \neq 0.33 \quad(\text{tỷ lệ nhóm \$30K–\$50K khác 33\%}) \end{aligned} \]
# Số quan sát thuộc nhóm $30K - $50K
x30_50 <- sum(dt1$AnnualIncome == "$30K - $50K")
# Tổng số quan sát
nTotal <- nrow(dt1)
# Kiểm định tỉ lệ một mẫu
test_income <- prop.test(x = x30_50,
n = nTotal,
p = 0.33,
alternative = "two.sided",
conf.level = 0.95)
test_income
##
## 1-sample proportions test with continuity correction
##
## data: x30_50 out of nTotal, null probability 0.33
## X-squared = 0.46381, df = 1, p-value = 0.4958
## alternative hypothesis: true p is not equal to 0.33
## 95 percent confidence interval:
## 0.3195204 0.3351018
## sample estimates:
## p
## 0.3272637
Kết luận
Vì \(p\text{-value} = 0.4958 > 0.05\), ta không bác bỏ giả thuyết không \[ H_0: p = 0.33. \] Khoảng tin cậy 95% \([0.3195,\;0.3351]\) bao gồm giá trị \(0.33\), củng cố rằng không có đủ bằng chứng thống kê để khẳng định tỷ lệ nhóm thu nhập $30K–$50K khác 33%.
Chọn ba cặp biến:
MaritalStatus và Homeowner
AnnualIncome và ProductFamily
MaritalStatus và ProductFamily
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.4.3
library(ggplot2)
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.4.3
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
library(tibble)
## Warning: package 'tibble' was built under R version 4.4.3
# 1) MaritalStatus & Homeowner
table_MH <- table(dt1$MaritalStatus, dt1$Homeowner)
pc_MH <- round(prop.table(table_MH, margin = 1) * 100, 2)
df_MH <- as.data.frame.matrix(pc_MH)
# In bảng với font lớn và responsive
kable(df_MH, format = "html",
caption = "Bảng 4.X: Tỷ lệ % Homeowner theo MaritalStatus") %>%
kable_styling(bootstrap_options = c("striped","hover","condensed","responsive"),
full_width = FALSE,
font_size = 16) %>% # tăng cỡ chữ
scroll_box(width = "100%", height = "200px") # khung cuộn nếu quá ngang
| N | Y | |
|---|---|---|
| M | 25.04 | 74.96 |
| S | 54.16 | 45.84 |
Nhận xét mối quan hệ giữa MaritalStatus và Homeowner
Chênh lệch rõ rệt giữa hai nhóm:
Xu hướng chung: Việc sở hữu nhà gắn liền mật thiết với tình trạng hôn nhân. Những người đã kết hôn có xu hướng ổn định và cam kết lâu dài hơn, dẫn đến khả năng mua hoặc sở hữu nhà cao hơn đáng kể so với người độc thân.
Kết luận sơ bộ: Có mối liên kết rõ ràng giữa tình trạng hôn nhân và quyền sở hữu nhà – tình trạng “Married” đi đôi với cơ hội và khả năng sở hữu nhà tốt hơn so với “Single”.
library(dplyr)
library(tidyr)
library(ggplot2)
library(RColorBrewer)
# Chuẩn bị dữ liệu
table_MH <- table(dt1$MaritalStatus, dt1$Homeowner)
df_MH_long <- as.data.frame(table_MH) %>%
group_by(Var1) %>%
mutate(Percent = Freq / sum(Freq) * 100) %>%
ungroup() %>%
rename(
MaritalStatus = Var1,
Homeowner = Var2
)
# 1) Biểu đồ cột xếp chồng (Stacked %)
ggplot(df_MH_long, aes(x = MaritalStatus, y = Percent, fill = Homeowner)) +
geom_col() +
scale_y_continuous(labels = scales::percent_format(scale = 1)) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Tỷ lệ % Chủ nhà theo Tình trạng hôn nhân",
x = "Tình trạng hôn nhân",
y = "Tỷ lệ (%)",
fill = "Chủ nhà"
) +
theme_minimal(base_size = 16) +
theme(
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold", hjust = 0.5)
)
# 2) Biểu đồ cột nhóm (Counts)
ggplot(df_MH_long, aes(x = MaritalStatus, y = Freq, fill = Homeowner)) +
geom_col(position = "dodge") +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Số lượng Chủ nhà theo Tình trạng hôn nhân",
x = "Tình trạng hôn nhân",
y = "Số lượng",
fill = "Chủ nhà"
) +
theme_minimal(base_size = 16) +
theme(
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold", hjust = 0.5)
)
Mối quan hệ giữa MaritalStatus và Homeowner
Biểu đồ cột xếp chồng (Tỷ lệ %)
Biểu đồ xếp chồng thể hiện tỷ lệ phần trăm chủ nhà (“Y”) và không chủ nhà (“N”) trong mỗi nhóm tình trạng hôn nhân. Từ đó rút ra được:
Biểu đồ cột nhóm (Số lượng)
Biểu đồ nhóm cho thấy số lượng tuyệt đối của chủ nhà và không chủ nhà trong mỗi tình trạng hôn nhân:
Cả hai biểu đồ đều đồng thuận rằng có mối liên kết mạnh giữa tình trạng hôn nhân và khả năng sở hữu nhà. Người đã kết hôn có xu hướng và điều kiện thuận lợi hơn để trở thành chủ nhà, trong khi người độc thân thường vẫn chưa đến giai đoạn ổn định lâu dài để mua bất động sản. Mối quan hệ này phản ánh những yếu tố kinh tế – xã hội như thu nhập gia đình, cam kết lâu dài và nhu cầu an cư của từng nhóm nhân khẩu.
Giả thuyết
Thực hiện kiểm định trong R
# Tạo bảng chéo
tab_MH <- table(dt1$MaritalStatus, dt1$Homeowner)
# Kiểm định Chi-squared
chi_MH <- chisq.test(tab_MH)
chi_MH
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tab_MH
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
Kiểm định Chi-bình phương cho MaritalStatus và Homeowner
Kết quả:
\[ \chi^2 = 1241.2,\quad df = 1,\quad p\text{-value} < 2.2\times10^{-16}. \]
Vì \(p\text{-value} < 0.05\), ta
bác bỏ giả thuyết không
\[
H_0:\; \text{MaritalStatus và Homeowner độc lập}.
\]
Điều này cho thấy có mối liên hệ có ý nghĩa thống kê giữa hai biến.
Thảo luận bản chất mối quan hệ
Từ bảng tần suất chéo và biểu đồ, ta thấy tỷ lệ chủ nhà (“Y”) trong nhóm Married rất cao (khoảng 75%), trong khi nhóm Single chỉ khoảng 46%.
Sự khác biệt lớn này không phải ngẫu nhiên mà phản ánh xu hướng
xã hội: người đã kết hôn thường có xu hướng ổn định và cam kết lâu dài
hơn, dẫn đến khả năng sở hữu nhà cao hơn so với người độc thân.
Kết quả kiểm định khẳng định rằng mối liên kết này là thống kê
có ý nghĩa, phù hợp với kỳ vọng thực tiễn về mối quan hệ giữa
tình trạng hôn nhân và quyền sở hữu nhà.
# 1. Bảng tần số chéo (Counts)
tab_AP <- table(dt1$AnnualIncome, dt1$ProductFamily)
tab_AP
##
## Drink Food Non-Consumable
## $10K - $30K 267 2232 591
## $110K - $130K 59 468 116
## $130K - $150K 56 556 148
## $150K + 25 199 49
## $30K - $50K 421 3340 840
## $50K - $70K 193 1705 472
## $70K - $90K 156 1221 332
## $90K - $110K 73 432 108
# 2. Tỷ lệ phần trăm theo hàng (mỗi mức thu nhập chia 100%)
prop_AP_row <- round(prop.table(tab_AP, margin = 1) * 100, 2)
prop_AP_row
##
## Drink Food Non-Consumable
## $10K - $30K 8.64 72.23 19.13
## $110K - $130K 9.18 72.78 18.04
## $130K - $150K 7.37 73.16 19.47
## $150K + 9.16 72.89 17.95
## $30K - $50K 9.15 72.59 18.26
## $50K - $70K 8.14 71.94 19.92
## $70K - $90K 9.13 71.45 19.43
## $90K - $110K 11.91 70.47 17.62
# 3. Tỷ lệ phần trăm theo cột (mỗi nhóm sản phẩm chia 100%)
prop_AP_col <- round(prop.table(tab_AP, margin = 2) * 100, 2)
prop_AP_col
##
## Drink Food Non-Consumable
## $10K - $30K 21.36 21.98 22.25
## $110K - $130K 4.72 4.61 4.37
## $130K - $150K 4.48 5.48 5.57
## $150K + 2.00 1.96 1.84
## $30K - $50K 33.68 32.90 31.63
## $50K - $70K 15.44 16.79 17.77
## $70K - $90K 12.48 12.03 12.50
## $90K - $110K 5.84 4.25 4.07
# 4. Hiển thị bảng đẹp với kableExtra
library(kableExtra)
# Bảng counts
kable(as.data.frame.matrix(tab_AP), caption = "Bảng: Số lượng theo AnnualIncome và ProductFamily") %>%
kable_styling(full_width = FALSE)
| Drink | Food | Non-Consumable | |
|---|---|---|---|
| $10K - $30K | 267 | 2232 | 591 |
| $110K - $130K | 59 | 468 | 116 |
| $130K - $150K | 56 | 556 | 148 |
| $150K + | 25 | 199 | 49 |
| $30K - $50K | 421 | 3340 | 840 |
| $50K - $70K | 193 | 1705 | 472 |
| $70K - $90K | 156 | 1221 | 332 |
| $90K - $110K | 73 | 432 | 108 |
# Bảng % theo hàng
kable(as.data.frame.matrix(prop_AP_row), caption = "Bảng: Tỷ lệ % theo hàng (AnnualIncome)") %>%
kable_styling(full_width = FALSE)
| Drink | Food | Non-Consumable | |
|---|---|---|---|
| $10K - $30K | 8.64 | 72.23 | 19.13 |
| $110K - $130K | 9.18 | 72.78 | 18.04 |
| $130K - $150K | 7.37 | 73.16 | 19.47 |
| $150K + | 9.16 | 72.89 | 17.95 |
| $30K - $50K | 9.15 | 72.59 | 18.26 |
| $50K - $70K | 8.14 | 71.94 | 19.92 |
| $70K - $90K | 9.13 | 71.45 | 19.43 |
| $90K - $110K | 11.91 | 70.47 | 17.62 |
# Bảng % theo cột
kable(as.data.frame.matrix(prop_AP_col), caption = "Bảng: Tỷ lệ % theo cột (ProductFamily)") %>%
kable_styling(full_width = FALSE)
| Drink | Food | Non-Consumable | |
|---|---|---|---|
| $10K - $30K | 21.36 | 21.98 | 22.25 |
| $110K - $130K | 4.72 | 4.61 | 4.37 |
| $130K - $150K | 4.48 | 5.48 | 5.57 |
| $150K + | 2.00 | 1.96 | 1.84 |
| $30K - $50K | 33.68 | 32.90 | 31.63 |
| $50K - $70K | 15.44 | 16.79 | 17.77 |
| $70K - $90K | 12.48 | 12.03 | 12.50 |
| $90K - $110K | 5.84 | 4.25 | 4.07 |
Nhận xét bảng tần số chéo và tỷ lệ phần trăm giữa AnnualIncome & ProductFamily
| AnnualIncome | Drink (%) | Food (%) | Non-Consumable (%) |
|---|---|---|---|
| $10K–$30K | 8.64 | 72.23 | 19.13 |
| $30K–$50K | 9.15 | 72.59 | 18.26 |
| $50K–$70K | 8.14 | 71.94 | 19.92 |
| $70K–$90K | 9.13 | 71.45 | 19.43 |
| $90K–$110K | 11.91 | 70.47 | 17.62 |
| $110K–$130K | 9.18 | 72.78 | 18.04 |
| $130K–$150K | 7.37 | 73.16 | 19.47 |
| $150K+ | 9.16 | 72.89 | 17.95 |
| AnnualIncome | Drink (%) | Food (%) | Non-Consumable (%) |
|---|---|---|---|
| $10K–$30K | 21.36 | 21.98 | 22.25 |
| $30K–$50K | 33.68 | 32.90 | 31.63 |
| $50K–$70K | 15.44 | 16.79 | 17.77 |
| $70K–$90K | 12.48 | 12.03 | 12.50 |
| $90K–$110K | 5.84 | 4.25 | 4.07 |
| $110K–$130K | 4.72 | 4.61 | 4.37 |
| $130K–$150K | 4.48 | 5.48 | 5.57 |
| $150K+ | 2.00 | 1.96 | 1.84 |
Tổng quan
library(dplyr)
library(ggplot2)
library(scales)
library(RColorBrewer)
# Chuẩn bị dữ liệu dài
tab_AP <- table(dt1$AnnualIncome, dt1$ProductFamily)
df_AP <- as.data.frame(tab_AP) %>%
rename(AnnualIncome = Var1, ProductFamily = Var2, Count = Freq) %>%
group_by(AnnualIncome) %>%
mutate(Percent = Count / sum(Count) * 100) %>%
ungroup()
### 2. Alluvial (Sankey)
library(ggalluvial)
df_allu <- as.data.frame(tab_AP) %>%
rename(Income = Var1, Product = Var2, Freq = Freq)
ggplot(df_allu,
aes(axis1 = Income, axis2 = Product, y = Freq)) +
geom_alluvium(aes(fill = Income), width = 1/12) +
geom_stratum(width = 1/12, fill = "grey80", color = "grey40") +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
scale_fill_brewer(type = "qual", palette = "Set3") +
labs(title = "Alluvial Plot: AnnualIncome → ProductFamily",
y = "Số lượng", x = NULL) +
theme_minimal(base_size = 14)
# HEATMAP
# 1. Chuẩn bị bảng chéo AnnualIncome vs ProductFamily
tab_AP <- table(dt1$AnnualIncome, dt1$ProductFamily)
# 2. Chuyển sang data frame dài và tính phần trăm nếu muốn
df_heat <- as.data.frame(tab_AP) %>%
rename(AnnualIncome = Var1, ProductFamily = Var2, Count = Freq) %>%
group_by(AnnualIncome) %>%
mutate(Percent = Count / sum(Count) * 100) %>%
ungroup()
# 3. Vẽ heatmap (Count)
ggplot(df_heat, aes(x = ProductFamily, y = AnnualIncome, fill = Count)) +
geom_tile(color = "white", size = 0.3) +
geom_text(aes(label = Count), size = 3) +
scale_fill_gradient(low = "#f7fbff", high = "#08306b", name = "Count") +
labs(
title = "Heatmap số lượng: AnnualIncome vs ProductFamily",
x = "ProductFamily",
y = "Annual Income"
) +
theme_minimal(base_size = 14) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid = element_blank(),
plot.title = element_text(face = "bold", hjust = 0.5)
)
Nhận xét trực quan mối quan hệ giữa AnnualIncome và ProductFamily
Kết luận chung
Cả hai biểu đồ đều nhất quán:
Khuyến nghị chiến lược:
- Tập trung quảng bá “Food” cho nhóm thu nhập trung bình để gia tăng thị phần.
- Khai thác thêm tiềm năng “Drink” ở nhóm $30K–$50K và $90K–$110K thông qua chương trình khuyến mãi.
- Duy trì tính đa dạng danh mục “Non-Consumable” nhưng không đẩy mạnh tại phân khúc thu nhập cao vì nhu cầu hạn chế.
# Tạo bảng chéo
tab_AP <- table(dt1$AnnualIncome, dt1$ProductFamily)
# Kiểm định Chi-bình phương
chi_AP <- chisq.test(tab_AP)
chi_AP
##
## Pearson's Chi-squared test
##
## data: tab_AP
## X-squared = 14.84, df = 14, p-value = 0.3892
Kết quả kiểm định cho thấy:
\[ \chi^2 = 14.84,\quad df = 14,\quad p\text{-value} = 0.3892. \]
Kết luận
Vì \(p\text{-value} = 0.3892 > \alpha =
0.05\), ta không bác bỏ \(H_0\).
Điều này cho thấy không có bằng chứng thống kê để khẳng
định mức thu nhập ảnh hưởng đến việc lựa chọn nhóm sản phẩm — hai biến
có thể được coi là độc lập ở mức ý nghĩa 5%.
Thảo luận bản chất mối quan hệ
Bảng tần suất chéo và tỷ lệ % theo hàng đã cho thấy “Food” chiếm trên 70% ở mọi mức thu nhập, trong khi “Drink” và “Non-Consumable” dao động quanh 8–12% và 17–20%.
Alluvial Plot và Heatmap cũng thể hiện cấu trúc ổn định: luồng “Food” luôn dày nhất, không có thay đổi đáng kể khi thu nhập biến động.
Kết quả kiểm định khẳng định phân bố các nhóm sản phẩm không phụ thuộc vào phân khúc thu nhập khách hàng, phù hợp với giá trị p-value cao và cơ cấu phần trăm gần như đồng nhất qua các mức.
Như vậy, dù có sự khác biệt nhỏ về số lượng tuyệt đối, sở thích sản phẩm cơ bản (Food, Drink, Non-Consumable) không bị chi phối đáng kể bởi AnnualIncome trong tập dữ liệu này.
library(kableExtra)
# Tạo bảng tần suất chéo
tab <- table(dt1$MaritalStatus, dt1$ProductFamily)
# Tính tỷ lệ phần trăm theo hàng
row_pct <- prop.table(tab, margin = 1) * 100
# Gộp tần suất và tỷ lệ phần trăm thành 1 bảng ký hiệu như: 123 (45.6%)
tab_combined <- matrix(paste0(tab, " (", round(row_pct, 1), "%)"),
nrow = nrow(tab),
dimnames = dimnames(tab))
# Đổi thành dataframe để vẽ bảng
tab_df <- as.data.frame.matrix(tab_combined)
# Hiển thị bảng đẹp
kbl(tab_df, caption = "Bảng 4.3 tần suất chéo giữa MaritalStatus và ProductFamily (kèm % theo hàng)",
align = "c") %>%
kable_styling(full_width = FALSE, position = "center", font_size = 12, bootstrap_options = c("striped", "hover"))
| Drink | Food | Non-Consumable | |
|---|---|---|---|
| M | 628 (9.1%) | 4938 (71.9%) | 1300 (18.9%) |
| S | 622 (8.6%) | 5215 (72.5%) | 1356 (18.9%) |
Dựa vào bảng tần suất chéo giữa và , với tỷ lệ phần trăm được tính theo từng hàng, ta có thể đưa ra một số nhận xét sau:
Từ đó, có thể thấy không có sự khác biệt rõ ràng trong xu hướng lựa chọn nhóm sản phẩm giữa người đã kết hôn và người độc thân. Tuy nhiên, để xác định liệu những khác biệt nhỏ này có mang ý nghĩa thống kê hay không, cần thực hiện kiểm định chi-bình phương ().
library(ggplot2)
library(dplyr)
# Dữ liệu tần suất
df_bar <- as.data.frame(table(dt1$MaritalStatus, dt1$ProductFamily))
colnames(df_bar) <- c("MaritalStatus", "ProductFamily", "Count")
# Vẽ biểu đồ nhóm có label
ggplot(df_bar, aes(x = ProductFamily, y = Count, fill = MaritalStatus)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
geom_text(aes(label = Count),
position = position_dodge(width = 0.8),
vjust = -0.3, size = 3.8) +
scale_fill_manual(values = c("#1F77B4", "#FF7F0E")) +
labs(title = "Số lượng nhóm sản phẩm theo tình trạng hôn nhân",
x = "Nhóm sản phẩm", y = "Số lượng",
fill = "Tình trạng hôn nhân") +
theme_minimal(base_size = 13) +
theme(axis.text.x = element_text(angle = 20, hjust = 1),
plot.title = element_text(face = "bold", size = 14))
Biểu đồ cột nhóm cho thấy phân phối số lượng sản phẩm tiêu dùng theo từng nhóm tình trạng hôn nhân (). Cả hai nhóm ( và ) đều có xu hướng mua nhiều sản phẩm thuộc nhóm , ít hơn là nhóm , và thấp nhất là nhóm .
Mặc dù có sự khác biệt nhỏ về số lượng sản phẩm được mua giữa hai nhóm, đặc biệt trong nhóm và , tuy nhiên mức độ chênh lệch không lớn và không thể hiện rõ xu hướng tiêu dùng đặc thù theo tình trạng hôn nhân. Do đó, biểu đồ gợi ý rằng có thể tồn tại một mối liên hệ nhẹ, nhưng không mạnh giữa hai biến này.
# Tính phần trăm theo hàng (tức theo từng MaritalStatus)
df_percent <- df_bar %>%
group_by(MaritalStatus) %>%
mutate(Percent = Count / sum(Count) * 100)
# Thêm nhãn phần trăm
ggplot(df_percent, aes(x = MaritalStatus, y = Percent, fill = ProductFamily)) +
geom_bar(stat = "identity", position = "stack", width = 0.6) +
geom_text(aes(label = paste0(round(Percent, 1), "%")),
position = position_stack(vjust = 0.5), size = 3.6, color = "black") +
scale_fill_brewer(palette = "Pastel2") +
scale_y_continuous(labels = scales::percent_format(scale = 1)) +
labs(title = "Tỷ lệ phần trăm nhóm sản phẩm theo tình trạng hôn nhân",
x = "Tình trạng hôn nhân", y = "Tỷ lệ (%)",
fill = "Nhóm sản phẩm") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"))
# Tạo bảng chéo
tab_MP <- table(dt1$MaritalStatus, dt1$ProductFamily)
# Kiểm định Chi-bình phương
chi_MP <- chisq.test(tab_MP)
chi_MP
##
## Pearson's Chi-squared test
##
## data: tab_MP
## X-squared = 1.1617, df = 2, p-value = 0.5594
Nhận xét kết quả kiểm định Chi-bình phương giữa
maritalstatusvàproductfamily
\[ \begin{cases} H_0: & \text{Hai biến } \texttt{maritalstatus} \text{ và } \texttt{productfamily} \text{ là độc lập} \\ H_1: & \text{Hai biến } \texttt{maritalstatus} \text{ và } \texttt{productfamily} \text{ có mối liên quan} \end{cases} \]
\[ \chi^2 = 1.1617, \quad \text{df} = 2, \quad p\text{-value} = 0.5594 \]
Với mức ý nghĩa \(\alpha = 0.05\), vì \(p\text{-value} = 0.5594 > 0.05\), nên không đủ bằng chứng để bác bỏ giả thuyết không \(H_0\). Do đó, ta kết luận rằng hai biến và là về mặt thống kê.
Do không tìm thấy mối liên hệ có ý nghĩa thống kê, không cần thiết phải phân tích sâu thêm về bản chất mối quan hệ dựa trên bảng tần suất chéo hoặc biểu đồ phân phối. Tuy nhiên, bảng tần suất có thể được xem để hiểu rõ hơn về phân bố các nhóm trong từng biến.
Qua quá trình phân tích dữ liệu định tính về đặc điểm khách hàng và hành vi mua sắm, chúng ta có thể rút ra những nhận định quan trọng như sau:
Các biến định tính như (tình trạng hôn nhân), (giới tính), và (dòng sản phẩm) đóng vai trò trung tâm trong việc phân loại khách hàng cũng như hiểu rõ hơn về xu hướng tiêu dùng của họ.
Mặc dù một số biến thể hiện tính độc lập qua kiểm định thống kê (ví dụ: kiểm định Chi-bình phương cho thấy không có mối liên hệ ý nghĩa giữa và ), nhưng các biến khác lại có sự phân phối khác biệt rõ rệt giữa các nhóm, cho thấy hành vi và sở thích của khách hàng không đồng nhất mà có sự đa dạng đáng kể.
Đặc biệt, nhóm khách hàng ở các trạng thái hôn nhân khác nhau có xu hướng lựa chọn sản phẩm thuộc các nhóm khác nhau, phản ánh rõ sự ảnh hưởng của các đặc điểm cá nhân đến quyết định mua sắm. Ví dụ, khách hàng đã kết hôn có thể ưu tiên các sản phẩm gia đình hoặc tiện ích, trong khi khách hàng độc thân có xu hướng tập trung vào các sản phẩm cá nhân hơn.
Các kết quả phân tích cũng cho thấy sự khác biệt trong hành vi mua sắm theo giới tính, qua đó gợi ý doanh nghiệp có thể triển khai các chiến dịch marketing nhắm mục tiêu phù hợp để tăng hiệu quả.
Phân tích hiện tại chủ yếu dựa trên các biến định tính, chưa khai thác các biến định lượng như thu nhập, số lần mua, giá trị giao dịch trung bình, v.v. Việc này làm giới hạn khả năng hiểu sâu sắc hơn về hành vi chi tiết của khách hàng.
Một số nhóm phân loại trong dữ liệu có kích thước mẫu nhỏ, làm giảm độ tin cậy của các kiểm định thống kê và khả năng tổng quát hóa kết quả ra toàn bộ tập khách hàng.
Mức độ phức tạp của các mối quan hệ giữa các biến có thể không được phản ánh đầy đủ qua các kiểm định đơn giản như kiểm định Chi-bình phương, đặc biệt khi các yếu tố tương tác hoặc các biến ẩn có ảnh hưởng lớn nhưng chưa được xem xét.
Ngoài ra, dữ liệu thiếu thông tin về yếu tố thời gian và bối cảnh môi trường (như thời điểm mua hàng, các chương trình khuyến mãi, xu hướng thị trường), điều này hạn chế khả năng phân tích hành vi khách hàng một cách toàn diện và linh hoạt.
Doanh nghiệp nên tận dụng các đặc điểm định tính như tình trạng hôn nhân, giới tính để phát triển các chiến lược marketing cá nhân hóa, từ đó nâng cao mức độ hấp dẫn và phù hợp của các chương trình tiếp thị.
Việc phân loại sản phẩm rõ ràng theo nhóm khách hàng mục tiêu sẽ giúp tối ưu hóa danh mục sản phẩm, giảm chi phí tồn kho và tăng hiệu quả bán hàng.
Cần bổ sung và thu thập thêm các biến định lượng liên quan đến hành vi khách hàng như tần suất mua, giá trị đơn hàng trung bình, lịch sử giao dịch, nhằm tăng tính chính xác và độ sâu của các mô hình phân tích, dự đoán.
Khuyến khích doanh nghiệp áp dụng các phương pháp phân tích đa biến phức tạp hơn như phân tích nhân tố, phân tích cụm, mô hình hồi quy logistic hoặc machine learning để khám phá các mối quan hệ phức tạp giữa các yếu tố ảnh hưởng đến hành vi khách hàng.
Liệu có thể xây dựng các mô hình dự đoán hành vi mua hàng hiệu quả hơn khi kết hợp dữ liệu định tính với dữ liệu định lượng chi tiết hơn, như thu nhập, mức chi tiêu hoặc mức độ trung thành?
Có những yếu tố tâm lý, xã hội hoặc bối cảnh thị trường nào khác ảnh hưởng đến quyết định mua hàng mà hiện tại chưa được khai thác hoặc ghi nhận trong dữ liệu?
Phân tích xu hướng hành vi khách hàng theo thời gian, ví dụ như biến động theo mùa vụ, hiệu quả các chiến dịch marketing, hay phản ứng với các thay đổi trong danh mục sản phẩm, có thể cung cấp thêm nhiều hiểu biết quan trọng?
Làm thế nào để ứng dụng các công nghệ phân tích dữ liệu lớn, trí tuệ nhân tạo để tự động hóa và cá nhân hóa hơn nữa các chiến dịch marketing và quản lý quan hệ khách hàng (CRM)?
Ngoài ra, nghiên cứu sâu hơn về cách các yếu tố văn hóa, vùng miền và hành vi tiêu dùng của từng nhóm khách hàng ảnh hưởng đến lựa chọn sản phẩm cũng là một hướng đáng để mở rộng.
Với những hướng đi này, doanh nghiệp có thể không chỉ nâng cao hiệu quả hoạt động hiện tại mà còn tạo được lợi thế cạnh tranh bền vững trong thị trường ngày càng phức tạp và đa dạng.
Relative Risk (RR) – hay nguy cơ tương đối – là một chỉ số thống kê được sử dụng để so sánh nguy cơ xảy ra một sự kiện (thường là bệnh tật) giữa hai nhóm:
Relative Risk được định nghĩa là tỉ số 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:
\[ RR = \frac{P_{\text{exposed}}}{P_{\text{unexposed}}} \]
Dữ liệu thường được trình bày trong một bảng \(2 \times 2\) như sau:
\[ \begin{array}{|c|c|c|c|} \hline & \text{Bị bệnh} & \text{Không bệnh} & \text{Tổng cộng} \\ \hline \text{Phơi nhiễm} & a & b & a + b \\ \text{Không phơi nhiễm} & c & d & c + d \\ \hline \end{array} \]
Khi đó:
\[ RR = \frac{a / (a + b)}{c / (c + d)} \]
Một nghiên cứu về hút thuốc và ung thư phổi:
Ta có:
\[ RR = \frac{30 / 100}{10 / 100} = \frac{0.3}{0.1} = 3 \]
👉 Kết luận: Người hút thuốc có nguy cơ bị ung thư phổi gấp 3 lần so với người không hút thuốc.
\[ RR = \frac{EER}{CER} \]
Trong đó:
RR < 1 nếu nhóm nằm ở tử số có
nguy cơ xảy ra sự kiện thấp hơn.
👉 Đây là điều mong muốn nếu sự kiện là kết cục
xấu (ví dụ: tử vong).
# Tạo bảng tần số chéo
gender_homeowner_table <- table(dt1$Gender, dt1$Homeowner)
gender_homeowner_table
##
## N Y
## F 2826 4344
## M 2789 4100
# Bảng với tổng
knitr::kable(addmargins(gender_homeowner_table), caption = "Bảng tần số chéo Gender vs Homeowner (có tổng)")
| N | Y | Sum | |
|---|---|---|---|
| F | 2826 | 4344 | 7170 |
| M | 2789 | 4100 | 6889 |
| Sum | 5615 | 8444 | 14059 |
# Thực hiện kiểm định
chi_test_result <- chisq.test(gender_homeowner_table)
chi_test_result
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: gender_homeowner_table
## X-squared = 1.6344, df = 1, p-value = 0.2011
Diễn giải:
Do p-value > 0.05 nên không có đủ bằng chứng để bác bỏ giả
thuyết H0.
Kết luận: Không có mối liên hệ có ý nghĩa thống kê giữa Giới tính và
việc sở hữu nhà.
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.4.3
library(epitools)
# Tính xác suất sở hữu nhà theo giới tính
p_homeowner_female <- gender_homeowner_table["F", "Y"] / sum(gender_homeowner_table["F", ])
p_homeowner_male <- gender_homeowner_table["M", "Y"] / sum(gender_homeowner_table["M", ])
RR_gender_homeowner <- p_homeowner_female / p_homeowner_male
cat("Tỷ lệ sở hữu nhà ở Nữ (p1):", round(p_homeowner_female, 4), "\n")
## Tỷ lệ sở hữu nhà ở Nữ (p1): 0.6059
cat("Tỷ lệ sở hữu nhà ở Nam (p2):", round(p_homeowner_male, 4), "\n")
## Tỷ lệ sở hữu nhà ở Nam (p2): 0.5952
cat("Relative Risk (RR):", round(RR_gender_homeowner, 3), "\n")
## Relative Risk (RR): 1.018
riskratio(gender_homeowner_table, method="wald")
## $data
##
## N Y Total
## F 2826 4344 7170
## M 2789 4100 6889
## Total 5615 8444 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## F 1.0000000 NA NA
## M 0.9823291 0.9561812 1.009192
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## F NA NA NA
## M 0.195158 0.1964833 0.1950884
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
Diễn giải: Tỷ lệ sở hữu nhà ở Nữ bằng khoảng 1.018 lần so với
Nam.
RR gần 1 → sự khác biệt nhỏ và có thể không đáng kể.
RD <- p_homeowner_female - p_homeowner_male
cat("Risk Difference (RD):", round(RD, 4), "\n")
## Risk Difference (RD): 0.0107
Diễn giải: Tỷ lệ sở hữu nhà ở Nữ thấp hơn Nam khoảng 1.07%.
# Lấy giá trị từ bảng
a <- gender_homeowner_table["F", "Y"]
b <- gender_homeowner_table["F", "N"]
c <- gender_homeowner_table["M", "Y"]
d <- gender_homeowner_table["M", "N"]
# Tính Odds và OR
odds_female_homeowner <- a / b
odds_male_homeowner <- c / d
OR_gender_homeowner <- (a * d) / (b * c)
cat("Odds Nữ:", round(odds_female_homeowner, 3), "\n")
## Odds Nữ: 1.537
cat("Odds Nam:", round(odds_male_homeowner, 3), "\n")
## Odds Nam: 1.47
cat("Odds Ratio (Nữ vs Nam):", round(OR_gender_homeowner, 3), "\n")
## Odds Ratio (Nữ vs Nam): 1.046
OddsRatio(gender_homeowner_table, method = "wald", conf.level = 0.95)
## odds ratio lwr.ci upr.ci
## 0.9563518 0.8939173 1.0231469
Diễn giải: OR < 1 → odds sở hữu nhà ở Nữ thấp hơn Nam một
chút.
- OR = 1: odds bằng nhau.
- OR > 1: odds cao hơn ở nhóm Nữ.
- OR < 1: odds thấp hơn ở nhóm Nữ.
library(epitools)
# Tính OR và khoảng tin cậy
or_results <- oddsratio.wald(gender_homeowner_table)
or_results$measure
## odds ratio with 95% C.I.
## estimate lower upper
## F 1.0000000 NA NA
## M 0.9563518 0.8939173 1.023147
Diễn giải: - Nếu KTC 95% cho OR chứa 1 → không có sự khác biệt có ý nghĩa. - Nếu KTC 95% không chứa 1 → có sự khác biệt ý nghĩa.
| Thống kê | Giá trị |
|---|---|
| p-value | 0.2011 |
| RR | 1.018 |
| RD | 0.0107 |
| OR | 1.046 |