library(readr)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(dplyr)
##
## 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(skimr)
## Warning: package 'skimr' was built under R version 4.3.3
library(psych)
## Warning: package 'psych' was built under R version 4.3.3
##
## Attaching package: 'psych'
## The following objects are masked from 'package:ggplot2':
##
## %+%, alpha
library(csv)
## Warning: package 'csv' was built under R version 4.3.3
library(DT)
## Warning: package 'DT' was built under R version 4.3.3
library(pander)
## Warning: package 'pander' was built under R version 4.3.3
library(formattable)
## Warning: package 'formattable' was built under R version 4.3.3
library(htmltools)
##
## Attaching package: 'htmltools'
## The following object is masked from 'package:pander':
##
## p
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.3.3
##
## Attaching package: 'DescTools'
## The following objects are masked from 'package:psych':
##
## AUC, ICC, SD
library(epitools)
d <- read.csv("D:/PTDLDT/Supermarket Transactions.csv")
str(d)
## '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 ...
Các biến trong bộ dữ liệu bao gồm:
X
: biến số nguyên, có thể là chỉ số thứ tự của bản
ghi.
PurchaseDate
: ngày mua hàng, được lưu dưới dạng
chuỗi ký tự với định dạng “YYYY-MM-DD”.
CustomerID
: mã định danh khách hàng dưới dạng số
nguyên.
Gender
: giới tính khách hàng, ký hiệu bằng ký tự (F:
nữ, M: nam).
MaritalStatus
: tình trạng hôn nhân (S: độc thân, M:
đã kết hôn).
Homeowner
: trạng thái sở hữu nhà (Y: có nhà, N:
không có nhà).
Children
: số lượng con trong gia đình, kiểu số
nguyên.
AnnualIncome
: nhóm thu nhập hàng năm, được ghi dưới
dạng chuỗi ký tự (ví dụ: “$30K - $50K”).
City
: tên thành phố nơi khách hàng sinh
sống.
StateorProvince
: bang hoặc tỉnh, được lưu dưới dạng
chuỗi ký tự.
Country
: quốc gia, dưới dạng chuỗi ký tự.
ProductFamily
: nhóm sản phẩm chính, ví dụ như Food,
Drink,…
ProductDepartment
: phòng ban sản phẩm, ví dụ như
Snack Foods, Produce,…
ProductCategory
: danh mục sản phẩm cụ thể.
UnitsSold
: số lượng sản phẩm đã bán, kiểu số
nguyên.
Revenue
: doanh thu thu được từ giao dịch, kiểu số
thực (đơn vị USD).
Việc hiểu rõ cấu trúc và kiểu dữ liệu của các biến sẽ hỗ trợ rất nhiều trong việc phân tích và xử lý dữ liệu tiếp theo.
dldt <- c("Gender", "MaritalStatus", "Homeowner","AnnualIncome","City", "StateorProvince", "Country", "ProductFamily", "ProductDepartment", "ProductCategory")
dldt
## [1] "Gender" "MaritalStatus" "Homeowner"
## [4] "AnnualIncome" "City" "StateorProvince"
## [7] "Country" "ProductFamily" "ProductDepartment"
## [10] "ProductCategory"
dt <- d[, dldt]
head(dt)
## Gender MaritalStatus Homeowner AnnualIncome City StateorProvince
## 1 F S Y $30K - $50K Los Angeles CA
## 2 M M Y $70K - $90K Los Angeles CA
## 3 F M N $50K - $70K Bremerton WA
## 4 M M Y $30K - $50K Portland OR
## 5 F S Y $130K - $150K Beverly Hills CA
## 6 F M Y $10K - $30K Beverly Hills CA
## Country ProductFamily ProductDepartment ProductCategory
## 1 USA Food Snack Foods Snack Foods
## 2 USA Food Produce Vegetables
## 3 USA Food Snack Foods Snack Foods
## 4 USA Food Snacks Candy
## 5 USA Drink Beverages Carbonated Beverages
## 6 USA Food Deli Side Dishes
tail(dt)
## Gender MaritalStatus Homeowner AnnualIncome City StateorProvince
## 14054 F M N $10K - $30K Yakima WA
## 14055 F M Y $10K - $30K Bremerton WA
## 14056 F M Y $10K - $30K Walla Walla WA
## 14057 M S Y $30K - $50K Portland OR
## 14058 F S N $50K - $70K Spokane WA
## 14059 M S N $50K - $70K Portland OR
## Country ProductFamily ProductDepartment ProductCategory
## 14054 USA Non-Consumable Household Paper Products
## 14055 USA Food Baking Goods Baking Goods
## 14056 USA Food Frozen Foods Vegetables
## 14057 USA Drink Beverages Pure Juice Beverages
## 14058 USA Drink Dairy Dairy
## 14059 USA Non-Consumable Household Electrical
any(is.na(dt))
## [1] FALSE
Vậy bộ dữ liệu không có giá trị thiếu
# Kiểm tra kiểu dữ liệu của từng biến trong dldt
sapply(dt, class)
## Gender MaritalStatus Homeowner AnnualIncome
## "character" "character" "character" "character"
## City StateorProvince Country ProductFamily
## "character" "character" "character" "character"
## ProductDepartment ProductCategory
## "character" "character"
“character”, nghĩa là chuỗi ký tự (text).
Dựa trên kết quả kiểm tra kiểu dữ liệu, có thể thấy rằng tất cả các biến trong tập dữ liệu đều đang ở dạng chuỗi ký tự (character). Đây là dấu hiệu cho thấy dữ liệu chưa được xử lý đúng kiểu, đặc biệt là đối với các biến như AnnualIncome – lẽ ra nên ở dạng số (numeric) để phục vụ cho các phép tính thống kê hoặc phân tích định lượng. Bên cạnh đó, các biến phân loại như Gender, MaritalStatus, Homeowner, hay ProductCategory nên được chuyển sang kiểu factor để thuận tiện cho việc phân tích định tính và mô hình hóa. Việc để toàn bộ biến ở dạng chuỗi ký tự có thể gây ra nhiều hạn chế trong quá trình xử lý và phân tích dữ liệu, do đó cần thực hiện bước tiền xử lý để chuyển đổi các biến về đúng kiểu dữ liệu tương ứng.
dt <- data.frame(lapply(dt, as.factor))
Bảng tần suất
#Lập bảng tần suất của biến Gender
table(dt$Gender)/sum(nrow(dt))
##
## F M
## 0.5099936 0.4900064
Bảng tần số
#Lập bảng tần số biến Gender
table(dt$Gender)
##
## F M
## 7170 6889
Biểu đồ
gender_freq <- table(dt$Gender)
gender_pct <- gender_freq / nrow(dt)
# Bước 1: Chuyển bảng sang data.frame
gender_freq <- table(dt$Gender) # Đếm số lượng từng nhóm giới tính (ví dụ: "M", "F"), trả về đối tượng table
gender_df <- as.data.frame(gender_freq) # Chuyển từ table sang data.frame để xử lý dễ hơn trong ggplot2
colnames(gender_df) <- c("Gender", "Count") # Đặt tên cột rõ ràng: "Gender" là tên nhóm, "Count" là số lượng
# Bước 2: Tính phần trăm
gender_df$Percent <- gender_df$Count / sum(gender_df$Count) * 100
# Bước 3: Tạo nhãn giống như trong pie()
gender_df$Label <- paste0( # Ghép chuỗi để tạo nhãn
gender_df$Gender, " (", # Thêm tên giới tính và dấu mở ngoặc
round(gender_df$Percent, 1), "%)" # Làm tròn phần trăm 1 chữ số và thêm dấu %
)
# Bước 4: Vẽ biểu đồ tròn bằng ggplot2
ggplot(gender_df, aes(x = "", y = Count, fill = Gender)) + # Dữ liệu truyền vào: không chia trục x, y là số lượng, fill theo giới tính
geom_bar(stat = "identity", width = 1) + # Vẽ cột với chiều cao đúng theo dữ liệu (stat = "identity"), chiều rộng 1
coord_polar("y") + # Chuyển từ biểu đồ cột sang biểu đồ tròn bằng cách dùng tọa độ cực
theme_void() + # Bỏ toàn bộ trục, đường lưới và nền để làm sạch biểu đồ
labs(title = "Biểu đồ 1. Phân bố giới tính (Gender)") + # Thêm tiêu đề phía trên biểu đồ
geom_text(aes(label = Label), # Thêm nhãn phần trăm vào từng lát của biểu đồ
position = position_stack(vjust = 0.5), # Đặt vị trí nhãn ở giữa mỗi lát (vjust = 0.5 là canh giữa theo chiều dọc)
size = 5) + # Cỡ chữ của nhãn
scale_fill_manual(values = c("F" = "lightpink", # Gán màu hồng nhạt cho giới tính "F"
"M" = "lightblue")) # Gán màu xanh nhạt cho giới tính "M"
Nhận xét:
counts <- table(dt$Gender)
diff_count <- abs(counts["F"] - counts["M"])
Vậy trong bộ dữ liệu này có 50.9993598 % nữ và 49.0006402% nam.
Trong bộ dữ liệu, số lượng nữ là 7170, số lượng nam là 6889. Sự chênh lệch về số lượng giữa nữ và nam là 281. Tuy số lượng nữ có phần nhỉnh hơn, nhưng mức chênh lệch là không đáng kể so với tổng thể dữ liệu, cho thấy cơ cấu giới tính trong bộ dữ liệu tương đối cân bằng.
Bảng tần suất
#Lập bảng tần suất của biến Homeowner
table(dt$Homeowner)/sum(nrow(dt))
##
## N Y
## 0.3993883 0.6006117
Bảng tần số
#Lập bảng tần số biến Homeowner
table(dt$Homeowner)
##
## N Y
## 5615 8444
Biểu đồ
# Bước 1: Tạo bảng tần suất và chuyển sang data.frame
home_freq <- table(dt$Homeowner) # Đếm số lượng "Y" và "N"
home_df <- as.data.frame(home_freq) # Chuyển sang data.frame để vẽ bằng ggplot2
colnames(home_df) <- c("Homeowner", "Count") # Đặt lại tên cột
# Bước 2: Tính phần trăm
home_df$Percent <- home_df$Count / sum(home_df$Count) * 100 # Tính phần trăm
# Bước 3: Tạo nhãn để hiển thị trên biểu đồ
home_df$Label <- paste0(home_df$Homeowner, " (", round(home_df$Percent, 1), "%)")
# Bước 4: Vẽ biểu đồ tròn bằng ggplot2
ggplot(home_df, aes(x = "", y = Count, fill = Homeowner)) + # Biến "fill" sẽ phân màu theo "Y"/"N"
geom_bar(stat = "identity", width = 1) + # Tạo cột theo số lượng
coord_polar("y") + # Chuyển sang biểu đồ tròn
theme_void() + # Xóa trục và nền
labs(title = "Biểu đồ 2. Tỷ lệ sở hữu nhà (Homeowner)") + # Thêm tiêu đề
geom_text(aes(label = Label), # Nhãn phần trăm trên lát cắt
position = position_stack(vjust = 0.5),
size = 5) +
scale_fill_manual(values = c("Y" = "lightgreen", # Màu cho nhóm "Y"
"N" = "lightcoral")) # Màu cho nhóm "N"
Nhận xét:
counts_homeowner <- table(dt$Homeowner)
diff_homeowner <- abs(counts_homeowner["Y"] - counts_homeowner["N"])
Vậy trong bộ dữ liệu này có 39.9388292 % không có nhà và 60.0611708% có nhà.
Số lượng người sở hữu nhà là 8444, số lượng người không sở hữu là 5615.
Sự chênh lệch về số lượng giữa hai nhóm là 2829 người, nghĩa là số người có nhà nhiều hơn khá đáng kể so với số người không có nhà. Điều này cho thấy phần lớn khách hàng trong bộ dữ liệu thuộc nhóm đã sở hữu nhà, và sự khác biệt giữa hai nhóm là tương đối lớn, có thể ảnh hưởng đến các phân tích liên quan đến điều kiện kinh tế – xã hội.
Bảng tần suất
#Lập bảng tần suất của biến MaritalStatus
table(dt$MaritalStatus)/sum(nrow(dt))
##
## M S
## 0.4883704 0.5116296
Bảng tần số
#Lập bảng tần số của biến MaritalStatus
table(dt$MaritalStatus)
##
## M S
## 6866 7193
Biểu đồ
# Bước 1: Tạo bảng tần suất và chuyển sang data.frame
mar_freq <- table(dt$MaritalStatus) # Đếm số lượng từng nhóm trong biến MaritalStatus
mar_df <- as.data.frame(mar_freq) # Chuyển từ table sang data.frame
colnames(mar_df) <- c("MaritalStatus", "Count") # Đặt tên cột: MaritalStatus là nhóm, Count là số lượng
# Bước 2: Tính phần trăm
mar_df$Percent <- mar_df$Count / sum(mar_df$Count) * 100 # Tính phần trăm từng nhóm
# Bước 3: Tạo nhãn hiển thị
mar_df$Label <- paste0(mar_df$MaritalStatus, " (", round(mar_df$Percent, 1), "%)") # Ví dụ: "Single (45.7%)"
# Bước 4: Vẽ biểu đồ tròn bằng ggplot2
ggplot(mar_df, aes(x = "", y = Count, fill = MaritalStatus)) + # x = "" để gom lại thành một vòng tròn
geom_bar(stat = "identity", width = 1) + # Vẽ biểu đồ cột với chiều rộng 1 để tạo hình tròn
coord_polar("y") + # Chuyển sang tọa độ tròn (pie chart)
theme_void() + # Loại bỏ trục, lưới, nền
labs(title = "Biểu đồ 3. Phân bố tình trạng hôn nhân (MaritalStatus)") + # Thêm tiêu đề cho biểu đồ
geom_text(aes(label = Label), # Thêm nhãn phần trăm vào từng lát
position = position_stack(vjust = 0.5),
size = 5) +
scale_fill_brewer(palette = "Pastel1") # Dùng bảng màu nhẹ nhàng tự động (hoặc chọn palette khác)
Nhận xét:
# Đếm số người kết hôn (M) và độc thân (S)
ms_counts <- table(dt$MaritalStatus)
# Chênh lệch về số lượng giữa hai nhóm
ms_diff <- abs(ms_counts["M"] - ms_counts["S"])
Vậy trong bộ dữ liệu này có 48.8370439 % đã kết hôn và 51.1629561% độc thân.
Cụ thể, có 6866 người đã kết hôn và 7193 người độc thân. Mặc dù nhóm độc thân có số lượng cao hơn, nhưng sự chênh lệch chỉ là 327 người – một con số khá nhỏ so với tổng thể. Do đó, có thể nhận xét rằng hai nhóm hôn nhân trong bộ dữ liệu khá cân bằng, và không có sự khác biệt đáng kể giữa số lượng người đã kết hôn và người độc thân.
Bảng tần suất
# ---- bảng tỷ lệ % cho City ----
annual_prop <- prop.table(table(dt$AnnualIncome))
# Chuyển thành data‑frame
annual_pct_df <- as.data.frame(annual_prop)
names(annual_pct_df) <- c("AnnualIncome", "Ty_le") # đặt tên cột
# Nhân 100 để thành phần trăm
annual_pct_df$Ty_le <- round(100 * annual_pct_df$Ty_le, 2)
print(annual_pct_df)
## AnnualIncome Ty_le
## 1 $10K - $30K 21.98
## 2 $110K - $130K 4.57
## 3 $130K - $150K 5.41
## 4 $150K + 1.94
## 5 $30K - $50K 32.73
## 6 $50K - $70K 16.86
## 7 $70K - $90K 12.16
## 8 $90K - $110K 4.36
Bảng tần số
# Bảng tần suất cho City
annual_tab <- table(dt$AnnualIncome)
# Chuyển thành data‑frame 2 cột: City và Freq
annual_df <- as.data.frame(annual_tab)
names(annual_df) <- c("AnnualIncome", "So_luong") # đặt tên cột rõ ràng
print(annual_df)
## AnnualIncome So_luong
## 1 $10K - $30K 3090
## 2 $110K - $130K 643
## 3 $130K - $150K 760
## 4 $150K + 273
## 5 $30K - $50K 4601
## 6 $50K - $70K 2370
## 7 $70K - $90K 1709
## 8 $90K - $110K 613
Biểu đồ
library(ggplot2)
ggplot(dt, aes(x = AnnualIncome)) + # đặt biến AnnualIncome lên trục X.
geom_bar() +
coord_flip() + # xoay ngang cho gọn
labs(title = "Biểu đồ 4. Tần số theo Thu nhập",
x = "AnnualIncome", y = "Số thu nhập")
Nhận xét:
Nhóm thu nhập chiếm tỷ lệ cao nhất trong bộ dữ liệu là $30K - $50K, chiếm khoảng 32.73% tổng số mẫu khảo sát. Điều này cho thấy nhóm này là tệp khách hàng chính hoặc phổ biến nhất trong tập dữ liệu.
Một số nhóm thu nhập khác như $150K + có tỷ lệ rất thấp, chỉ khoảng 1.94%, cho thấy mức độ xuất hiện của họ trong dữ liệu không nhiều — có thể do họ ít quan tâm đến sản phẩm, hoặc nằm ngoài phân khúc thị trường mà doanh nghiệp đang hướng tới.
Sự phân bố thu nhập không đều phản ánh cơ cấu khách hàng của siêu thị hoặc đơn vị khảo sát: tập trung nhiều ở các nhóm thu nhập trung bình đến trung cao, trong khi nhóm thu nhập quá thấp hoặc quá cao xuất hiện ít hơn.
Đây có thể là dấu hiệu để doanh nghiệp điều chỉnh chiến lược tiếp cận thị trường, như tập trung nhiều hơn vào các nhóm thu nhập đang chiếm ưu thế, hoặc mở rộng các chính sách ưu đãi để thu hút nhóm khách hàng ít phổ biến hơn.
Bảng tần suất
# ---- bảng tỷ lệ % cho City ----
city_prop <- prop.table(table(dt$City)) # hoặc table(dt$City) / nrow(dt)
# Chuyển thành data‑frame
city_pct_df <- as.data.frame(city_prop)
names(city_pct_df) <- c("City", "Ty_le") # đặt tên cột
# Nhân 100 để thành phần trăm
city_pct_df$Ty_le <- round(100 * city_pct_df$Ty_le, 2)
print(city_pct_df)
## City Ty_le
## 1 Acapulco 2.72
## 2 Bellingham 1.02
## 3 Beverly Hills 5.77
## 4 Bremerton 5.93
## 5 Camacho 3.22
## 6 Guadalajara 0.53
## 7 Hidalgo 6.01
## 8 Los Angeles 6.59
## 9 Merida 4.65
## 10 Mexico City 1.38
## 11 Orizaba 3.30
## 12 Portland 6.23
## 13 Salem 9.86
## 14 San Andres 4.42
## 15 San Diego 6.16
## 16 San Francisco 0.92
## 17 Seattle 6.56
## 18 Spokane 6.22
## 19 Tacoma 8.94
## 20 Vancouver 4.50
## 21 Victoria 1.25
## 22 Walla Walla 1.14
## 23 Yakima 2.67
Bảng tần số
# Bảng tần suất cho City
city_tab <- table(dt$City)
# Chuyển thành data‑frame 2 cột: City và Freq
city_df <- as.data.frame(city_tab)
names(city_df) <- c("City", "So_luong") # đặt tên cột rõ ràng
print(city_df)
## City So_luong
## 1 Acapulco 383
## 2 Bellingham 143
## 3 Beverly Hills 811
## 4 Bremerton 834
## 5 Camacho 452
## 6 Guadalajara 75
## 7 Hidalgo 845
## 8 Los Angeles 926
## 9 Merida 654
## 10 Mexico City 194
## 11 Orizaba 464
## 12 Portland 876
## 13 Salem 1386
## 14 San Andres 621
## 15 San Diego 866
## 16 San Francisco 130
## 17 Seattle 922
## 18 Spokane 875
## 19 Tacoma 1257
## 20 Vancouver 633
## 21 Victoria 176
## 22 Walla Walla 160
## 23 Yakima 376
Biểu đồ
library(ggplot2)
ggplot(dt, aes(x = City)) + # đặt biến City lên trục X.
geom_bar() +
coord_flip() + # xoay ngang cho gọn
labs(title = "Biểu đồ 5. Tần số giao dịch theo City",
x = "City", y = "Số giao dịch")
Nhận xét:
- Trong bộ dữ liệu này, thành phố có tỷ lệ giao dịch cao nhất là Salem
với khoảng 9.86%, tiếp theo là Tacoma (8.94%), Los Angeles (6.59%) và
Seattle (6.56%).
Các thành phố nhỏ hơn như Hidalgo (6.01%) hoặc Guadalajara (0.53%) có tỷ lệ thấp hơn nhiều.
Điều này cho thấy giao dịch chủ yếu tập trung ở một số thành phố lớn với dân số hoặc hoạt động kinh tế cao hơn. Các thành phố nhỏ hơn đóng góp ít hơn vào tổng số giao dịch, có thể do quy mô thị trường nhỏ hoặc mức độ phổ biến của sản phẩm thấp.
Ngoài ra, việc phân bố này cũng có thể phản ánh chiến lược tiếp thị hoặc kênh phân phối mà siêu thị đang tập trung vào các khu vực đô thị lớn.
Bảng tần suất
#Lập bảng tần suất của biến StateorProvince
table(dt$StateorProvince)/sum(nrow(dt))
##
## 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
Bảng tần số
#Lập bảng tần số của biến StateorProvince
table(dt$StateorProvince)
##
## BC CA DF Guerrero Jalisco OR Veracruz WA
## 809 2733 815 383 75 2262 464 4567
## Yucatan Zacatecas
## 654 1297
Biểu đồ
ggplot(dt, aes(x = StateorProvince)) +
geom_bar() +
coord_flip() + # xoay trục cho gọn
labs(title = "Biều đồ 6. Tần số giao dịch theo State / Province",
x = "State / Province",
y = "Số giao dịch")
Nhận xét: Trong bộ dữ liệu này, bang hoặc tỉnh có tỷ lệ giao dịch lớn nhất là WA với khoảng 32.48%, tiếp theo là CA (19.44%) và OR (16.09%). Các bang như Jalisco (0.53%) và Guerrero (2.72%) chiếm tỷ lệ thấp hơn. Như vậy, dữ liệu cho thấy sự tập trung giao dịch cao ở một số bang chính.
Bảng tần suất
#Lập bảng tần suất của biến Country
table(dt$Country)/sum(nrow(dt))
##
## Canada Mexico USA
## 0.05754321 0.26232307 0.68013372
Bảng tần số
#Lập bảng tần số của biến Country
table(dt$Country)
##
## Canada Mexico USA
## 809 3688 9562
Biểu đồ
# Bước 1: Tạo bảng tần suất và chuyển sang data.frame
country_freq <- table(dt$Country) # Đếm số lượng từng quốc gia trong biến Country
country_df <- as.data.frame(country_freq) # Chuyển từ table sang data.frame để xử lý bằng ggplot2
colnames(country_df) <- c("Country", "Count") # Đặt lại tên cột: "Country" là tên nhóm, "Count" là số lượng
# Bước 2: Tính phần trăm
country_df$Percent <- country_df$Count / sum(country_df$Count) * 100 # Tính phần trăm
# Bước 3: Tạo nhãn phần trăm hiển thị trên lát cắt
country_df$Label <- paste0(country_df$Country, " (", round(country_df$Percent, 1), "%)") # Ví dụ: "USA (45.3%)"
# Bước 4: Vẽ biểu đồ tròn bằng ggplot2
ggplot(country_df, aes(x = "", y = Count, fill = Country)) + # Không chia trục x, chia màu theo Country
geom_bar(stat = "identity", width = 1) + # Vẽ cột theo số lượng, độ rộng 1 để làm hình tròn
coord_polar("y") + # Chuyển sang biểu đồ tròn
theme_void() + # Xóa trục, đường lưới và nền
labs(title = "Biểu đồ 7. Phân bố giao dịch theo Country") + # Tiêu đề biểu đồ
geom_text(aes(label = Label), # Thêm nhãn phần trăm vào giữa lát
position = position_stack(vjust = 0.5),
size = 4) +
scale_fill_brewer(palette = "Greens") # Tự động tạo màu dễ phân biệt giữa nhiều quốc gia
Nhận xét:
# Đếm số bản ghi theo quốc gia
cty_counts <- table(dt$Country)
# Chênh lệch về số lượng giữa quốc gia đông nhất và ít nhất
cty_diff <- max(cty_counts) - min(cty_counts)
Vậy trong bộ dữ liệu này có 5.7543211 % ở Canada, 26.2323067% ở Mexico và 68.0133722% ở USA.
Quốc gia đông nhất có 9562, quốc gia ít nhất có r
min(cty_counts)
.
Sự chênh lệch giữa hai quốc gia này là 8753 người.
Bảng tần suất
#Lập bảng tần suất của biến ProductFamily
table(dt$ProductFamily)/sum(nrow(dt))
##
## Drink Food Non-Consumable
## 0.08891102 0.72217085 0.18891813
Bảng tần số
#Lập bảng tần số của biến ProductFamily
table(dt$ProductFamily)
##
## Drink Food Non-Consumable
## 1250 10153 2656
Biểu đồ
# Bước 1: Tạo bảng tần suất và tính tỷ lệ phần trăm
pfreq <- sort(table(dt$ProductFamily), decreasing = TRUE) # Đếm số lượng mỗi nhóm ProductFamily và sắp xếp giảm dần
ppct <- pfreq / nrow(dt) # Tính tỷ lệ phần trăm của mỗi nhóm
# Bước 2: Chuyển sang data.frame để dùng ggplot2
product_df <- as.data.frame(pfreq) # Chuyển bảng tần suất sang data.frame
colnames(product_df) <- c("ProductFamily", "Count") # Đặt tên cột: tên nhóm và số lượng
product_df$Percent <- product_df$Count / sum(product_df$Count) * 100 # Tính phần trăm từng nhóm
product_df$Label <- paste0(product_df$ProductFamily, # Tạo nhãn hiển thị tên + phần trăm
" (", round(product_df$Percent, 1), "%)")
# Bước 3: Vẽ biểu đồ tròn bằng ggplot2
ggplot(product_df, aes(x = "", y = Count, fill = ProductFamily)) + # Dữ liệu biểu đồ: y là số lượng, chia màu theo nhóm
geom_bar(stat = "identity", width = 1) + # Vẽ cột (bar chart) có chiều rộng bằng 1 để tạo hình tròn
coord_polar("y") + # Chuyển bar chart thành biểu đồ tròn theo trục y
theme_void() + # Loại bỏ trục và nền (gọn gàng hơn)
labs(title = "Biểu đồ 8. Phân bố giao dịch theo Product Family") + # Thêm tiêu đề cho biểu đồ
geom_text(aes(label = Label), # Thêm nhãn (label) hiển thị trong lát cắt
position = position_stack(vjust = 0.5), # Đặt nhãn vào giữa mỗi lát
size = 4) + # Kích thước chữ của nhãn
scale_fill_brewer(palette = "Blues")
Nhận xét:
Trong bộ dữ liệu này, nhóm đồ uống chiếm khoảng 8.89%,
nhóm thức ăn chiếm khoảng 72.22%, và nhóm hàng không tiêu thụ được chiếm
khoảng 18.89%.
Về số lượng, nhóm thức ăn có 10153 giao dịch,
nhóm đồ uống có 1250 giao dịch, và nhóm hàng không tiêu thụ được có 2656
giao dịch. Điều này cho thấy nhóm thức ăn là hạng mục chiếm ưu thế rõ
rệt, với sự chênh lệch rất lớn về số lượng so với hai nhóm còn lại. Như
vậy, có thể nhận xét rằng phần lớn giao dịch trong bộ dữ liệu tập trung
vào các sản phẩm thực phẩm – đây là đặc điểm nổi bật trong cơ cấu mặt
hàng của siêu thị này.
Bảng tần suất
# Tạo bảng tần suất (hoặc tỷ lệ) rồi đổi thành data‑frame 2 cột
dep_tab <- prop.table(table(dt$ProductDepartment)) # hoặc table(dt$ProductDepartment)
dep_df <- as.data.frame(dep_tab) # ← biến thành 2 cột
# Đặt tên cột ngắn gọn
names(dep_df) <- c("ProductDepartment", "Ty_le") # nếu là tỷ lệ %
dep_df$Ty_le <- round(100 * dep_df$Ty_le, 2) # nhân 100 → %
print(dep_df)
## ProductDepartment Ty_le
## 1 Alcoholic Beverages 2.53
## 2 Baked Goods 3.02
## 3 Baking Goods 7.63
## 4 Beverages 4.84
## 5 Breakfast Foods 1.34
## 6 Canned Foods 6.95
## 7 Canned Products 0.78
## 8 Carousel 0.42
## 9 Checkout 0.58
## 10 Dairy 6.42
## 11 Deli 4.97
## 12 Eggs 1.41
## 13 Frozen Foods 9.83
## 14 Health and Hygiene 6.35
## 15 Household 10.10
## 16 Meat 0.63
## 17 Periodicals 1.44
## 18 Produce 14.18
## 19 Seafood 0.73
## 20 Snack Foods 11.38
## 21 Snacks 2.50
## 22 Starchy Foods 1.97
Bảng tần số
# Lập bảng tần số
dep_freq <- table(dt$ProductDepartment)
# Chuyển thành data‑frame 2 cột
dep_freq_df <- as.data.frame(dep_freq)
names(dep_freq_df) <- c("ProductDepartment", "So_luong") # đặt tên cột rõ ràng
print(dep_freq_df)
## ProductDepartment So_luong
## 1 Alcoholic Beverages 356
## 2 Baked Goods 425
## 3 Baking Goods 1072
## 4 Beverages 680
## 5 Breakfast Foods 188
## 6 Canned Foods 977
## 7 Canned Products 109
## 8 Carousel 59
## 9 Checkout 82
## 10 Dairy 903
## 11 Deli 699
## 12 Eggs 198
## 13 Frozen Foods 1382
## 14 Health and Hygiene 893
## 15 Household 1420
## 16 Meat 89
## 17 Periodicals 202
## 18 Produce 1994
## 19 Seafood 102
## 20 Snack Foods 1600
## 21 Snacks 352
## 22 Starchy Foods 277
Biểu đồ
ggplot(dt, aes(x = ProductDepartment)) +
geom_bar() +
coord_flip() + # xoay ngang nhãn cho dễ đọc
labs(title = "Biều đồ 9. Tần số giao dịch theo Product Department",
x = "Product Department",
y = "Số giao dịch")
Nhận xét:
# ----- tỷ lệ % cho ProductCategory -----
pc_prop_df <- prop.table(table(dt$ProductCategory)) |> # hoặc table(...)/nrow(dt)
as.data.frame() |> # thành 2 cột
setNames(c("Category", "Ty_le")) |> # đổi tên cột
transform(Ty_le = round(100 * Ty_le, 2)) # nhân 100 → %
print(pc_prop_df)
## Category Ty_le
## 1 Baking Goods 3.44
## 2 Bathroom Products 2.60
## 3 Beer and Wine 2.53
## 4 Bread 3.02
## 5 Breakfast Foods 2.97
## 6 Candles 0.32
## 7 Candy 2.50
## 8 Canned Anchovies 0.31
## 9 Canned Clams 0.38
## 10 Canned Oysters 0.25
## 11 Canned Sardines 0.28
## 12 Canned Shrimp 0.27
## 13 Canned Soup 2.87
## 14 Canned Tuna 0.62
## 15 Carbonated Beverages 1.10
## 16 Cleaning Supplies 1.34
## 17 Cold Remedies 0.66
## 18 Dairy 6.42
## 19 Decongestants 0.60
## 20 Drinks 0.96
## 21 Eggs 1.41
## 22 Electrical 2.53
## 23 Frozen Desserts 2.30
## 24 Frozen Entrees 0.84
## 25 Fruit 5.44
## 26 Hardware 0.92
## 27 Hot Beverages 1.61
## 28 Hygiene 1.40
## 29 Jams and Jellies 4.18
## 30 Kitchen Products 1.54
## 31 Magazines 1.44
## 32 Meat 5.41
## 33 Miscellaneous 0.30
## 34 Packaged Vegetables 0.34
## 35 Pain Relievers 1.37
## 36 Paper Products 2.45
## 37 Pizza 1.38
## 38 Plastic Products 1.00
## 39 Pure Juice Beverages 1.17
## 40 Seafood 0.73
## 41 Side Dishes 1.09
## 42 Snack Foods 11.38
## 43 Specialty 2.06
## 44 Starchy Foods 1.97
## 45 Vegetables 12.29
freq_df <- table(dt$ProductCategory) |> # Tạo bảng tần suất đếm số lần xuất hiện mỗi category trong cột ProductCategory của dataframe dt
as.data.frame() |> # Chuyển bảng tần suất (kiểu table) thành dataframe để dễ xử lý (2 cột: category và số lượng)
setNames(c("Category", "So_luong")) # Đổi tên 2 cột của dataframe thành "Category" (tên category) và "So_luong" (số lần xuất hiện)
print(freq_df)
## Category So_luong
## 1 Baking Goods 484
## 2 Bathroom Products 365
## 3 Beer and Wine 356
## 4 Bread 425
## 5 Breakfast Foods 417
## 6 Candles 45
## 7 Candy 352
## 8 Canned Anchovies 44
## 9 Canned Clams 53
## 10 Canned Oysters 35
## 11 Canned Sardines 40
## 12 Canned Shrimp 38
## 13 Canned Soup 404
## 14 Canned Tuna 87
## 15 Carbonated Beverages 154
## 16 Cleaning Supplies 189
## 17 Cold Remedies 93
## 18 Dairy 903
## 19 Decongestants 85
## 20 Drinks 135
## 21 Eggs 198
## 22 Electrical 355
## 23 Frozen Desserts 323
## 24 Frozen Entrees 118
## 25 Fruit 765
## 26 Hardware 129
## 27 Hot Beverages 226
## 28 Hygiene 197
## 29 Jams and Jellies 588
## 30 Kitchen Products 217
## 31 Magazines 202
## 32 Meat 761
## 33 Miscellaneous 42
## 34 Packaged Vegetables 48
## 35 Pain Relievers 192
## 36 Paper Products 345
## 37 Pizza 194
## 38 Plastic Products 141
## 39 Pure Juice Beverages 165
## 40 Seafood 102
## 41 Side Dishes 153
## 42 Snack Foods 1600
## 43 Specialty 289
## 44 Starchy Foods 277
## 45 Vegetables 1728
Biểu đồ
# Vẽ biểu đồ cột tần suất ProductCategory
ggplot(dt, aes(x = reorder(ProductCategory, ProductCategory, function(x) -length(x)))) +
geom_bar(fill = "steelblue") +
coord_flip() + # Xoay trục để nhãn dễ đọc hơn
labs(title = "Biểu đồ 10. Tần suất giao dịch theo Product Category",
x = "Product Category",
y = "Số giao dịch") +
theme_minimal()
Nhận xét: Trong bộ dữ liệu, nhóm sản phẩm có tỷ lệ giao dịch cao nhất là Vegetables với 12.29%, tiếp theo là Snack Foods (11.38%) và Dairy (6.42%). Các nhóm đóng hộp như Canned Oysters (0.25%) và Canned Clams (0.38%) chiếm tỷ lệ rất nhỏ, cho thấy sự ưu tiên mua hàng tươi và đồ ăn nhẹ.
Trong thống kê, khi làm việc với dữ liệu dạng nhị phân (ví dụ: có/không, nam/nữ, đạt/không đạt…), một đại lượng quan trọng thường được quan tâm là tỷ lệ (proportion) – ký hiệu là \(p\). Hai kỹ thuật phổ biến để phân tích tỷ lệ trong quần thể là ước lượng khoảng tin cậy và kiểm định giả thuyết.
Giả sử chúng ta có một mẫu ngẫu nhiên gồm \(n\) phần tử, trong đó có \(x\) phần tử có đặc điểm quan tâm. Khi đó, tỷ lệ mẫu được tính là:
\[ \hat{p} = \frac{x}{n} \]
Để ước lượng tỷ lệ tổng thể \(p\), ta xây dựng khoảng tin cậy với mức tin cậy \((1 - \alpha) \times 100\%\). Khi kích thước mẫu đủ lớn, khoảng tin cậy được tính như sau:
\[ \hat{p} \pm z_{\alpha/2} \cdot \sqrt{ \frac{\hat{p}(1 - \hat{p})}{n} } \]
Trong đó:
Mục tiêu là kiểm định giả thuyết về tỷ lệ tổng thể \(p\). Ví dụ:
Thống kê kiểm định được sử dụng là:
\[ z = \frac{ \hat{p} - p_0 }{ \sqrt{ \frac{p_0 (1 - p_0)}{n} } } \]
So sánh giá trị \(z\) với giá trị tới hạn từ bảng phân phối chuẩn để đưa ra kết luận:
Nếu \(|z| > z_{\alpha/2}\), bác bỏ \(H_0\) (trường hợp hai phía)
Hoặc dùng p-value để đối chiếu với mức ý nghĩa \(\alpha\)
Ước lượng khoảng tin cậy
# Số người nữ (Gender = "F") và tổng số quan sát
n_female <- sum(dt$Gender == "F")
n_total <- nrow(dt)
# Tính khoảng tin cậy 95% và kiểm định giả thuyết với tỷ lệ kỳ vọng p = 0.5
test_female <- prop.test(n_female, n_total, p = 0.5, correct = FALSE)
Tỷ lệ nữ trong dữ liệu là 0.51.
Khoảng tin cậy 95% cho tỷ lệ này là từ 0.5017 đến 0.5183.
Kiểm định giả thuyết
Giả thuyết đặt ra như sau:
H₀: p = 0.5 (Tỷ lệ nữ thuộc danh mục gender là 50%)
H₁: p ≠ 0.5 (Tỷ lệ nữ thuộc danh mục gender khác 50%)
# Kiểm định giả thuyết với prop.test
test_female <- prop.test(n_female, n_total, p = 0.5, correct = FALSE)
test_female
##
## 1-sample proportions test without continuity correction
##
## data: n_female out of n_total, null probability 0.5
## X-squared = 5.6164, df = 1, p-value = 0.01779
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5017287 0.5182531
## sample estimates:
## p
## 0.5099936
#Giá trị thống kê Chi-bình phương: 5.6164 với bậc tự do 1.
#Giá trị p = 0.01779.
#Khoảng tin cậy 95% cho tỉ lệ nữ trong tổng thể là từ 0.5017 đến 0.5183.
#Ước lượng tỉ lệ mẫu: 0.5099936 (~50.999%).
Với mức ý nghĩa \(\alpha = 0.05\), kết quả kiểm định cho thấy giá trị p là 0.0178.
Vì p-value nhỏ hơn 0.05, chúng ta bác bỏ giả thuyết H₀. Vậy tỷ lệ nữ khác 50% .
# test_female$p.value: Giá trị p (p-value) từ kiểm định tỷ lệ nữ
# ifelse(...): Hàm điều kiện trong R. Nếu điều kiện đúng thì lấy phần 2, sai thì lấy phần 3
Ước lượng khoảng tin cậy cho tỷ lệ người đã kết hôn
# Số người đã kết hôn (ký hiệu M) và tổng số quan sát
n_married <- sum(dt$MaritalStatus == "M")
n_total <- nrow(dt)
# Tính khoảng tin cậy 95% và kiểm định giả thuyết
test_married <- prop.test(n_married, n_total, p = 0.5, correct = FALSE)
test_married
##
## 1-sample proportions test without continuity correction
##
## data: n_married out of n_total, null probability 0.5
## X-squared = 7.6057, df = 1, p-value = 0.005818
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.4801120 0.4966352
## sample estimates:
## p
## 0.4883704
#Giá trị thống kê Chi-bình phương: 7.6057 (df=1).
#Giá trị p = 0.005818.
#Khoảng tin cậy 95% cho tỉ lệ người đã kết hôn trong tổng thể: từ 48.01% đến 49.66%.
#Tỉ lệ mẫu ước lượng: 48.84%.
#p = 0.5: Tỷ lệ kỳ vọng trong giả thuyết không H₀ (ở đây: H₀: tỷ lệ đã kết hôn = 0.5)
#correct = FALSE: Không dùng hiệu chỉnh liên tục (continuity correction), cho kết quả gần với lý thuyết hơn khi mẫu lớn
Tỷ lệ người đã kết hôn trong dữ liệu là 0.4884.
Khoảng tin cậy 95% cho tỷ lệ này là từ 0.4801 đến 0.4966.
# test_married$conf.int[1] → Cận dưới
# test_married$conf.int[2] → Cận trên
Kiểm định giả thuyết
Giả thuyết:
H₀: p = 0.5 (Tỷ lệ người đã kết hôn là 50%)
H₁: p ≠ 0.5 (Tỷ lệ người đã kết hôn khác 50%)
Giá trị p từ kiểm định là: p_value = 0.0058
Với mức ý nghĩa \(\alpha = 0.05\), Vì P_value < 0.05, ta bác bỏ giả thuyết H₀. Do đó, có bằng chứng thống kê cho thấy tỷ lệ người đã kết hôn khác 50% trong tổng thể.
# Đếm số sản phẩm là Food
n_drink <- sum(dt$ProductFamily == "Drink", na.rm = TRUE)
# Tổng số quan sát
n_total <- nrow(dt)
# Tỷ lệ sản phẩm Food
prop_drink <- n_drink / n_total
prop_drink
## [1] 0.08891102
Kiểm định giả thuyết:
Giả thuyết:
H₀: p <= 0.09 (Tỷ lệ sản phẩm thuộc nhóm Drink là 9%)
H₁: p > 0.09 (Tỷ lệ sản phẩm thuộc nhóm Drink lớn hơn 9%)
test_drink <- prop.test(n_drink, n_total, p = 0.09, alternative = "greater", correct = FALSE)
# # alternative = "greater": kiểm định 1 phía, H1: tỷ lệ thực tế lớn hơn 0.09
test_drink
##
## 1-sample proportions test without continuity correction
##
## data: n_drink out of n_total, null probability 0.09
## X-squared = 0.20357, df = 1, p-value = 0.6741
## alternative hypothesis: true p is greater than 0.09
## 95 percent confidence interval:
## 0.08504142 1.00000000
## sample estimates:
## p
## 0.08891102
#Giá trị thống kê Chi-bình phương: 0.20357 (df=1).
#Giá trị p = 0.6741.
#Khoảng tin cậy 95% cho tỉ lệ sản phẩm Drink trong tổng thể là từ 8.5% đến 100% (khoảng trên không giới hạn vì kiểm định một phía).
#Tỉ lệ mẫu ước lượng: 8.89%.
Khoảng tin cậy 95% cho tỷ lệ thực tế p: từ 0.0850 đến 1.0000
Giá trị p từ kiểm định: P_value = 0.6741.
Với mức ý nghĩa \(\alpha = 0.05\), 0.6741, Vì P_value > 0.05, ta không đủ cơ sở bác bỏ giả thuyết H₀.
→ Kết luận: Tỷ lệ sản phẩm Drink không lớn hơn 9%.
Kiểm định:
H₀: p₁ - p₂ = 0 (tỷ lệ Mexico bằng Canada)
H₁: p₁ - p₂ < 0 (tỷ lệ Mexico nhỏ hơn Canada)
tbl <- table(dt$Country)
tbl
##
## Canada Mexico USA
## 809 3688 9562
x <- c(tbl["Mexico"], tbl["Canada"]) # Số lượng khách hàng mỗi nhóm
n <- c(sum(tbl[c("Mexico", "Canada")]), sum(tbl[c("Mexico", "Canada")]))
prop.test(x = x, n = n, alternative = "less", correct = FALSE)
##
## 2-sample test for equality of proportions without continuity correction
##
## data: x out of n
## X-squared = 3686.3, df = 1, p-value = 1
## alternative hypothesis: less
## 95 percent confidence interval:
## -1.0000000 0.6535284
## sample estimates:
## prop 1 prop 2
## 0.8201023 0.1798977
X-squared = 3686.3 Giá trị thống kê kiểm định chi bình phương (Chi-squared). Giá trị này rất lớn, cho thấy có sự khác biệt lớn giữa hai tỷ lệ quan sát được. Tuy nhiên, điều quan trọng là phải xem xét hướng kiểm định mới có thể đưa ra kết luận chính xác. df = 1 Số bậc tự do của kiểm định (vì so sánh 2 nhóm nên df = 1).
p-value = 1 Đây là xác suất để quan sát được sự chênh lệch như vậy (hoặc lớn hơn) nếu H₀ là đúng. Với p-value = 1, điều đó có nghĩa là không có bằng chứng nào ủng hộ H₁: p₁ < p₂. Kết quả này là do hướng kiểm định không phù hợp với dữ liệu thực tế.
alternative hypothesis: less Kiểm định 1 phía với giả thuyết đối: p₁ < p₂ (Mexico < Canada). Nhưng dữ liệu cho thấy Mexico chiếm 82%, còn Canada chỉ 18%, nên giả thuyết này ngược với thực tế, dẫn đến p-value = 1.
95% confidence interval: (-1.0000000, 0.6535284) Khoảng tin cậy cho hiệu p₁ - p₂. Khoảng này bao gồm cả số 0 và phần dương lớn, cho thấy chưa đủ bằng chứng để khẳng định p₁ < p₂.
sample estimates:
Với mức ý nghĩa α = 0.05, vì p-value = 1 > 0.05, ta không bác bỏ giả thuyết H₀. Không có đủ bằng chứng thống kê để kết luận rằng tỷ lệ khách hàng Mexico thấp hơn Canada.
# Bảng tần số chéo (cross-tabulation) giữa Gender và Homeowner
table_gender_homeowner <- table(dt$Gender, dt$Homeowner)
table_gender_homeowner
##
## N Y
## F 2826 4344
## M 2789 4100
diff_count <- table_gender_homeowner["F", "Y"] - table_gender_homeowner["M", "Y"]
diff_not_owner_count <-table_gender_homeowner["F", "N"]- table_gender_homeowner["M", "N"]
cat("Nữ sở hữu nhà nhiều hơn nam:", diff_count, "người")
## Nữ sở hữu nhà nhiều hơn nam: 244 người
cat("Nữ không sở hữu nhà nhiều hơn nam:", diff_not_owner_count, "người\n")
## Nữ không sở hữu nhà nhiều hơn nam: 37 người
Nhận xét:
Trong bộ dữ liệu, có 2826 nữ không sở hữu nhà và 4344 nữ sở hữu nhà. Ngoài ra, có 2789 nam không sở hữu nhà và 4100 nam sở hữu nhà.
Số người nữ sở hữu nhà nhiều hơn số người nam sở hữu nhà bằng 244 người.
Số người nữ không sở hữu nhà nhiều hơn số người nam không sở hữu nhà bằng 37 người.
# Chuyển sang dataframe
df_gh <- as.data.frame(table_gender_homeowner)
colnames(df_gh) <- c("Gender", "Homeowner", "Count")
# Vẽ biểu đồ
library(ggplot2)
ggplot(df_gh, aes(Gender, Count, fill = Homeowner)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Bieu do 11. So luong so huu nha theo gioi tinh",
x = "Gioi tinh", y = "So luong", fill = "So huu nha") +
theme_minimal()
# Tổng số mẫu
total_samples <- nrow(dt)
# Tỷ lệ tuyệt đối trên tổng số mẫu
prop_abs <- table_gender_homeowner / total_samples
# Tỷ lệ tương đối trong từng giới tính (theo hàng)
prop_by_gender <- prop.table(table_gender_homeowner, margin = 1) #tính tỷ lệ cho từng hàng, tức là chia từng giá trị trong hàng đó cho tổng của hàng đó.
# In tỷ lệ tuyệt đối trên tổng số mẫu
print("Tỷ lệ tuyệt đối (trên tổng số mẫu):")
## [1] "Tỷ lệ tuyệt đối (trên tổng số mẫu):"
print(round(prop_abs, 4))
##
## N Y
## F 0.2010 0.3090
## M 0.1984 0.2916
Nhận xét:
# In tỷ lệ tương đối trong từng giới tính
print("Tỷ lệ tương đối trong từng giới tính:")
## [1] "Tỷ lệ tương đối trong từng giới tính:"
print(round(prop_by_gender, 4))
##
## N Y
## F 0.3941 0.6059
## M 0.4048 0.5952
Nhận xét:
Giả thuyết kiểm định:
H₀: Giới tính và việc sở hữu nhà là hai biến độc lập.
H₁: Giới tính và việc sở hữu nhà có liên quan.
Thực hiện kiểm định Chi-bình phương
chi_test <- chisq.test(table_gender_homeowner)
chi_test
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table_gender_homeowner
## X-squared = 1.6344, df = 1, p-value = 0.2011
chi_sq_value <- round(chi_test$statistic, 4)
df_value <- chi_test$parameter
p_value <- round(chi_test$p.value, 4)
Giá trị thống kê Chi-bình phương: 1.6344
Bậc tự do (df): 1
Giá trị p: p_value = 0.2011
Với mức ý nghĩa \(\alpha = 0.05\), vì p_value ≥ 0.05, ta không đủ cơ sở để bác bỏ giả thuyết H₀, tức là không có mối quan hệ đáng kể giữa giới tính và việc sở hữu nhà.
# Tạo bảng tần số chéo
table_marital_homeowner <- table(dt$MaritalStatus, dt$Homeowner)
# Hiển thị bảng
table_marital_homeowner
##
## N Y
## M 1719 5147
## S 3896 3297
# Tính chênh lệch số lượng người sở hữu nhà giữa Married (M) và Single (S)
diff_owner_count <- table_marital_homeowner["M", "Y"] - table_marital_homeowner["S", "Y"]
# Tính chênh lệch số lượng người KHÔNG sở hữu nhà giữa Married (M) và Single (S)
diff_not_owner_count <- table_marital_homeowner["M", "N"] - table_marital_homeowner["S", "N"]
# In kết quả sở hữu nhà
if (diff_owner_count > 0) {
message("Người đã kết hôn sở hữu nhiều nhà hơn người độc thân: ", diff_owner_count, " người")
} else {
message("Người độc thân sở hữu nhiều nhà hơn người kết hôn: ", abs(diff_owner_count), " người")
}
## Người đã kết hôn sở hữu nhiều nhà hơn người độc thân: 1850 người
# In kết quả KHÔNG sở hữu nhà
if (diff_not_owner_count > 0) {
message("Người đã kết hôn KHÔNG sở hữu nhà nhiều hơn người độc thân: ", diff_not_owner_count, " người")
} else {
message("Người độc thân KHÔNG sở hữu nhà nhiều hơn người kết hôn: ", abs(diff_not_owner_count), " người")
}
## Người độc thân KHÔNG sở hữu nhà nhiều hơn người kết hôn: 2177 người
Nhận xét:
Trong bộ dữ liệu, có 3896 người độc thân không sở hữu nhà và 3297 người độc thân sở hữu nhà. Ngoài ra, có 1719 người đã kết hôn không sở hữu nhà và 5147 người đã kết hôn sở hữu nhà.
Số người đã kết hôn sở hữu nhà nhiều hơn người độc thân là 1850 người.
Người độc thân không sở hữu nhà nhiều hơn người đã kết hôn là 2177 người.
# Chuyển bảng tần số sang dạng data.frame dài
data_long <- as.data.frame.table(table_marital_homeowner)
colnames(data_long) <- c("MaritalStatus", "Homeowner", "Count")
# Lọc nhóm M và S luôn trong ggplot
ggplot(data_long[data_long$MaritalStatus %in% c("M", "S"), ],
aes(x = MaritalStatus, y = Count, fill = Homeowner)) +
geom_col(position = "dodge") +
scale_fill_manual(values = c("N" = "#FF9999", "Y" = "#66CC99"),
labels = c("Khong so huu nha", "So huu nha")) +
labs(title = "Bieu do 12. So sanh so luong nguoi so huu va khong so huu nha theo tinh trang hon nhan",
x = "Tinh trang hon nhan",
y = "So luong nguoi",
fill = "So huu nha") +
theme_minimal()
# Bảng tần số giữa MaritalStatus và Homeowner
table_marital_homeowner <- table(dt$MaritalStatus, dt$Homeowner)
# Tỷ lệ tuyệt đối so với tổng số mẫu (toàn bộ dataset)
prop_abs <- table_marital_homeowner / total_samples
# Tỷ lệ theo từng hàng (trong từng MaritalStatus)
prop_by_marital <- prop.table(table_marital_homeowner, margin = 1)
# Làm tròn để dễ xem
prop_abs <- round(prop_abs, 4)
prop_by_marital <- round(prop_by_marital, 4)
# In ra bảng tỷ lệ tuyệt đối với tiêu đề
cat("=== Tỷ lệ tuyệt đối theo từng nhóm MaritalStatus và Homeowner (so với tổng số mẫu) ===\n")
## === Tỷ lệ tuyệt đối theo từng nhóm MaritalStatus và Homeowner (so với tổng số mẫu) ===
print(prop_abs)
##
## N Y
## M 0.1223 0.3661
## S 0.2771 0.2345
cat("\n=== Tỷ lệ tương đối trong từng nhóm MaritalStatus (tỷ lệ theo hàng) ===\n")
##
## === Tỷ lệ tương đối trong từng nhóm MaritalStatus (tỷ lệ theo hàng) ===
print(prop_by_marital)
##
## N Y
## M 0.2504 0.7496
## S 0.5416 0.4584
Trong tổng số mẫu, tỷ lệ những người đã kết hôn (M) sở hữu nhà
(Y) là khoảng 36.61%, và không sở hữu nhà (N) là 12.23%.
Ở nhóm người độc thân (S), tỷ lệ sở hữu nhà là 23.45%, và không sở hữu nhà là 27.71%.
Xét tỷ lệ tương đối trong từng nhóm MaritalStatus:
Như vậy, ta thấy rằng người đã kết hôn có xu hướng sở hữu nhà cao hơn so với người độc thân.
Giả thuyết kiểm định:
H₀: Tình trạng hôn nhân và việc sở hữu nhà là hai biến độc lập.
H₁: Tình trạng hôn nhân và việc sở hữu nhà có liên quan.
# Thực hiện kiểm định Chi-bình phương
chisq_result <- chisq.test(table_marital_homeowner)
# Xem kết quả
chisq_result
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table_marital_homeowner
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
# Trích xuất thông tin
# Trích xuất thông tin
chi_sq_value1 <- round(chisq_result$statistic, 4)
df_value1 <- chisq_result$parameter
p_value1 <- round(chisq_result$p.value, 4)
Giá trị thống kê Chi-bình phương: 1241.2177
Bậc tự do (df): 1
Giá trị p: p_value = 0
Với mức ý nghĩa \(\alpha = 0.05\), vì p_value < 0.05, ta bác bỏ giả thuyết H₀, tức là có mối quan hệ giữa tình trạng hôn nhân và việc sở hữu nhà.
Nhận xét:
Người đã kết hôn (M) có tỷ lệ sở hữu nhà cao hơn đáng kể so với người độc thân (S).
Người đã kết hôn (Married - M) có tỷ lệ sở hữu nhà cao, đạt 74.96%, trong khi đó người độc thân (Single - S) chỉ có tỷ lệ sở hữu nhà là 45.84%.
Ngược lại, tỷ lệ không sở hữu nhà ở nhóm độc thân (54.16%) cao hơn nhiều so với nhóm đã kết hôn (25.04%).
Điều này phản ánh những điểm quan trọng sau:
Kinh tế và trách nhiệm gia đình: Người đã kết hôn thường có thu nhập ổn định hơn hoặc có sự hỗ trợ về tài chính từ cả hai vợ chồng, từ đó khả năng sở hữu nhà cũng cao hơn. Họ thường có xu hướng tìm kiếm sự ổn định lâu dài, dành sự ưu tiên cho việc mua nhà để xây dựng tổ ấm và chăm sóc con cái.
Lối sống và ưu tiên của người độc thân: Người độc thân có thể lựa chọn thuê nhà hoặc các hình thức lưu trú linh hoạt hơn, do không bị ràng buộc bởi trách nhiệm gia đình. Họ có thể ưu tiên các cơ hội nghề nghiệp hoặc di chuyển địa lý, nên việc sở hữu nhà không phải là ưu tiên hàng đầu.
# Tạo bảng tần số chéo giữa AnnualIncome và ProductCategory
table_income_product <- table(dt$AnnualIncome, dt$ProductCategory)
# Hiển thị bảng tần số
table_income_product
##
## Baking Goods Bathroom Products Beer and Wine Bread
## $10K - $30K 119 85 80 108
## $110K - $130K 18 16 14 23
## $130K - $150K 22 19 15 24
## $150K + 11 8 3 10
## $30K - $50K 151 116 121 134
## $50K - $70K 86 50 61 63
## $70K - $90K 59 51 39 50
## $90K - $110K 18 20 23 13
##
## Breakfast Foods Candles Candy Canned Anchovies Canned Clams
## $10K - $30K 111 6 76 10 12
## $110K - $130K 7 1 16 2 1
## $130K - $150K 28 2 19 1 3
## $150K + 7 1 8 1 1
## $30K - $50K 143 21 127 14 20
## $50K - $70K 62 7 60 8 6
## $70K - $90K 42 7 29 6 7
## $90K - $110K 17 0 17 2 3
##
## Canned Oysters Canned Sardines Canned Shrimp Canned Soup
## $10K - $30K 5 8 9 98
## $110K - $130K 4 2 0 19
## $130K - $150K 3 1 2 17
## $150K + 1 1 0 8
## $30K - $50K 10 18 16 137
## $50K - $70K 5 5 7 67
## $70K - $90K 5 3 2 50
## $90K - $110K 2 2 2 8
##
## Canned Tuna Carbonated Beverages Cleaning Supplies
## $10K - $30K 13 36 47
## $110K - $130K 3 6 8
## $130K - $150K 5 3 7
## $150K + 3 6 4
## $30K - $50K 28 51 51
## $50K - $70K 19 20 35
## $70K - $90K 10 23 25
## $90K - $110K 6 9 12
##
## Cold Remedies Dairy Decongestants Drinks Eggs Electrical
## $10K - $30K 23 174 22 30 37 74
## $110K - $130K 2 38 4 9 9 20
## $130K - $150K 6 49 5 8 15 21
## $150K + 3 17 0 4 4 8
## $30K - $50K 32 299 31 46 67 114
## $50K - $70K 12 160 8 19 36 57
## $70K - $90K 10 126 10 16 20 47
## $90K - $110K 5 40 5 3 10 14
##
## Frozen Desserts Frozen Entrees Fruit Hardware Hot Beverages
## $10K - $30K 75 20 150 31 48
## $110K - $130K 17 10 29 3 11
## $130K - $150K 17 5 48 10 9
## $150K + 8 2 10 1 5
## $30K - $50K 112 35 252 41 79
## $50K - $70K 44 21 136 25 33
## $70K - $90K 36 18 104 13 26
## $90K - $110K 14 7 36 5 15
##
## Hygiene Jams and Jellies Kitchen Products Magazines Meat
## $10K - $30K 36 137 47 49 156
## $110K - $130K 6 31 5 17 41
## $130K - $150K 14 32 14 9 52
## $150K + 4 8 3 1 14
## $30K - $50K 62 185 74 65 253
## $50K - $70K 37 103 51 36 115
## $70K - $90K 29 71 20 18 100
## $90K - $110K 9 21 3 7 30
##
## Miscellaneous Packaged Vegetables Pain Relievers Paper Products
## $10K - $30K 10 9 42 70
## $110K - $130K 1 1 7 19
## $130K - $150K 6 1 8 17
## $150K + 0 2 5 8
## $30K - $50K 8 20 61 101
## $50K - $70K 14 8 34 67
## $70K - $90K 2 7 30 46
## $90K - $110K 1 0 5 17
##
## Pizza Plastic Products Pure Juice Beverages Seafood Side Dishes
## $10K - $30K 50 41 34 17 36
## $110K - $130K 13 6 9 3 2
## $130K - $150K 12 7 5 8 8
## $150K + 1 2 5 5 3
## $30K - $50K 59 33 52 44 53
## $50K - $70K 31 31 25 11 23
## $70K - $90K 15 17 26 12 23
## $90K - $110K 13 4 9 2 5
##
## Snack Foods Specialty Starchy Foods Vegetables
## $10K - $30K 329 65 70 385
## $110K - $130K 85 13 18 74
## $130K - $150K 83 18 15 87
## $150K + 35 5 5 32
## $30K - $50K 533 96 85 551
## $50K - $70K 274 50 48 300
## $70K - $90K 184 32 28 215
## $90K - $110K 77 10 8 84
# 1. Tạo dip từ bảng table_income_product
dip <- as.data.frame(table_income_product)
colnames(dip) <- c("AnnualIncome", "ProductCategory", "Frequency")
# 2. Lọc Top 5 sản phẩm theo tổng số lượng mua
library(dplyr)
top_products <- dip %>%
group_by(ProductCategory) %>%
summarise(Total = sum(Frequency)) %>%
arrange(desc(Total)) %>%
slice_head(n = 5) %>%
pull(ProductCategory)
dip_top <- dip %>% filter(ProductCategory %in% top_products)
# 3. Vẽ biểu đồ với dip_top
library(RColorBrewer)
ggplot(dip_top, aes(x = AnnualIncome, y = Frequency, fill = ProductCategory)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_brewer(palette = "Set2") + # hoặc "Dark2", "Pastel1", "Accent", ...
labs(title = "Biểu đồ 13. Top 5 sản phẩm theo số lượng mua theo mức thu nhập",
x = "Mức thu nhập",
y = "Số lượng",
fill = "Sản phẩm") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# top_products <- dip %>%
# group_by(ProductCategory) %>% # Gom nhóm theo danh mục sản phẩm
# summarise(Total = sum(Frequency)) %>% # Tính tổng số lượng mua của từng sản phẩm
# arrange(desc(Total)) %>% # Sắp xếp giảm dần theo tổng số lượng
# slice_head(n = 5) %>% # Lấy 5 sản phẩm đứng đầu
# pull(ProductCategory) # Lấy tên các sản phẩm này thành vector
#ggplot(dip_top, aes(...)): định nghĩa dữ liệu và mapping:
#Trục X là AnnualIncome (mức thu nhập),
#Trục Y là Frequency (số lượng mua),
#Màu cột theo ProductCategory.
#geom_bar(stat = "identity", position = "dodge"):
#stat = "identity": lấy chính giá trị Frequency để vẽ chiều cao cột,
#position = "dodge": các cột của từng loại sản phẩm sẽ đứng cạnh nhau (không chồng lên).
#scale_fill_brewer(palette = "Set2"): chọn bảng màu đẹp, nhẹ mắt từ thư viện RColorBrewer.
#labs(...): đặt tiêu đề, nhãn trục và chú thích màu.
#theme_minimal(): giao diện biểu đồ đơn giản, ít chi tiết rối mắt.
#theme(axis.text.x = element_text(angle = 45, hjust = 1)): xoay nhãn trục X 45 độ để dễ đọc, căn chỉnh hợp lý.
Dựa trên bảng tần số chéo giữa biến AnnualIncome và ProductCategory, chúng ta nhận thấy những xu hướng tiêu dùng khác nhau theo mức thu nhập:
Nhóm thu nhập từ $30K - $50K có số lượng giao dịch cao nhất ở hầu hết các danh mục, chẳng hạn như:
Snack Foods: 533 giao dịch.
Vegetables: 551 giao dịch.
Dairy: 299 giao dịch.
Đây có thể là do nhóm này đại diện cho tầng lớp trung lưu, có khả năng chi tiêu cao nhưng vẫn chú trọng các mặt hàng thiết yếu, phổ biến.
Nhóm thu nhập thấp ($10K - $30K) cũng có lượng giao dịch tương đối cao, đặc biệt trong các danh mục như:
Vegetables: 385 giao dịch.
Snack Foods: 329 giao dịch.
Điều này cho thấy nhu cầu mua các sản phẩm cơ bản và giá cả phải chăng vẫn rất lớn trong nhóm thu nhập thấp.
Nhóm thu nhập cao ($150K+ và $130K - $150K) có số lượng giao dịch thấp hơn rõ rệt:
Chỉ có 35 giao dịch ở Snack Foods và 32 ở Vegetables.
Có thể do số lượng khách thuộc nhóm này ít hơn trong tập dữ liệu hoặc hành vi tiêu dùng khác biệt (ít mua hàng tại siêu thị, ưu tiên sản phẩm cao cấp hoặc mua sắm online).
## --- 2. TỶ LỆ TUYỆT ĐỐI so với toàn bộ mẫu --------------------
total_samples <- nrow(dt)
prop_abs_ip <- round(table_income_product / total_samples, 4)
cat("\n>>> Tỷ lệ tuyệt đối (trên tổng số mẫu):\n")
##
## >>> Tỷ lệ tuyệt đối (trên tổng số mẫu):
print(prop_abs_ip)
##
## Baking Goods Bathroom Products Beer and Wine Bread
## $10K - $30K 0.0085 0.0060 0.0057 0.0077
## $110K - $130K 0.0013 0.0011 0.0010 0.0016
## $130K - $150K 0.0016 0.0014 0.0011 0.0017
## $150K + 0.0008 0.0006 0.0002 0.0007
## $30K - $50K 0.0107 0.0083 0.0086 0.0095
## $50K - $70K 0.0061 0.0036 0.0043 0.0045
## $70K - $90K 0.0042 0.0036 0.0028 0.0036
## $90K - $110K 0.0013 0.0014 0.0016 0.0009
##
## Breakfast Foods Candles Candy Canned Anchovies Canned Clams
## $10K - $30K 0.0079 0.0004 0.0054 0.0007 0.0009
## $110K - $130K 0.0005 0.0001 0.0011 0.0001 0.0001
## $130K - $150K 0.0020 0.0001 0.0014 0.0001 0.0002
## $150K + 0.0005 0.0001 0.0006 0.0001 0.0001
## $30K - $50K 0.0102 0.0015 0.0090 0.0010 0.0014
## $50K - $70K 0.0044 0.0005 0.0043 0.0006 0.0004
## $70K - $90K 0.0030 0.0005 0.0021 0.0004 0.0005
## $90K - $110K 0.0012 0.0000 0.0012 0.0001 0.0002
##
## Canned Oysters Canned Sardines Canned Shrimp Canned Soup
## $10K - $30K 0.0004 0.0006 0.0006 0.0070
## $110K - $130K 0.0003 0.0001 0.0000 0.0014
## $130K - $150K 0.0002 0.0001 0.0001 0.0012
## $150K + 0.0001 0.0001 0.0000 0.0006
## $30K - $50K 0.0007 0.0013 0.0011 0.0097
## $50K - $70K 0.0004 0.0004 0.0005 0.0048
## $70K - $90K 0.0004 0.0002 0.0001 0.0036
## $90K - $110K 0.0001 0.0001 0.0001 0.0006
##
## Canned Tuna Carbonated Beverages Cleaning Supplies
## $10K - $30K 0.0009 0.0026 0.0033
## $110K - $130K 0.0002 0.0004 0.0006
## $130K - $150K 0.0004 0.0002 0.0005
## $150K + 0.0002 0.0004 0.0003
## $30K - $50K 0.0020 0.0036 0.0036
## $50K - $70K 0.0014 0.0014 0.0025
## $70K - $90K 0.0007 0.0016 0.0018
## $90K - $110K 0.0004 0.0006 0.0009
##
## Cold Remedies Dairy Decongestants Drinks Eggs Electrical
## $10K - $30K 0.0016 0.0124 0.0016 0.0021 0.0026 0.0053
## $110K - $130K 0.0001 0.0027 0.0003 0.0006 0.0006 0.0014
## $130K - $150K 0.0004 0.0035 0.0004 0.0006 0.0011 0.0015
## $150K + 0.0002 0.0012 0.0000 0.0003 0.0003 0.0006
## $30K - $50K 0.0023 0.0213 0.0022 0.0033 0.0048 0.0081
## $50K - $70K 0.0009 0.0114 0.0006 0.0014 0.0026 0.0041
## $70K - $90K 0.0007 0.0090 0.0007 0.0011 0.0014 0.0033
## $90K - $110K 0.0004 0.0028 0.0004 0.0002 0.0007 0.0010
##
## Frozen Desserts Frozen Entrees Fruit Hardware Hot Beverages
## $10K - $30K 0.0053 0.0014 0.0107 0.0022 0.0034
## $110K - $130K 0.0012 0.0007 0.0021 0.0002 0.0008
## $130K - $150K 0.0012 0.0004 0.0034 0.0007 0.0006
## $150K + 0.0006 0.0001 0.0007 0.0001 0.0004
## $30K - $50K 0.0080 0.0025 0.0179 0.0029 0.0056
## $50K - $70K 0.0031 0.0015 0.0097 0.0018 0.0023
## $70K - $90K 0.0026 0.0013 0.0074 0.0009 0.0018
## $90K - $110K 0.0010 0.0005 0.0026 0.0004 0.0011
##
## Hygiene Jams and Jellies Kitchen Products Magazines Meat
## $10K - $30K 0.0026 0.0097 0.0033 0.0035 0.0111
## $110K - $130K 0.0004 0.0022 0.0004 0.0012 0.0029
## $130K - $150K 0.0010 0.0023 0.0010 0.0006 0.0037
## $150K + 0.0003 0.0006 0.0002 0.0001 0.0010
## $30K - $50K 0.0044 0.0132 0.0053 0.0046 0.0180
## $50K - $70K 0.0026 0.0073 0.0036 0.0026 0.0082
## $70K - $90K 0.0021 0.0051 0.0014 0.0013 0.0071
## $90K - $110K 0.0006 0.0015 0.0002 0.0005 0.0021
##
## Miscellaneous Packaged Vegetables Pain Relievers Paper Products
## $10K - $30K 0.0007 0.0006 0.0030 0.0050
## $110K - $130K 0.0001 0.0001 0.0005 0.0014
## $130K - $150K 0.0004 0.0001 0.0006 0.0012
## $150K + 0.0000 0.0001 0.0004 0.0006
## $30K - $50K 0.0006 0.0014 0.0043 0.0072
## $50K - $70K 0.0010 0.0006 0.0024 0.0048
## $70K - $90K 0.0001 0.0005 0.0021 0.0033
## $90K - $110K 0.0001 0.0000 0.0004 0.0012
##
## Pizza Plastic Products Pure Juice Beverages Seafood
## $10K - $30K 0.0036 0.0029 0.0024 0.0012
## $110K - $130K 0.0009 0.0004 0.0006 0.0002
## $130K - $150K 0.0009 0.0005 0.0004 0.0006
## $150K + 0.0001 0.0001 0.0004 0.0004
## $30K - $50K 0.0042 0.0023 0.0037 0.0031
## $50K - $70K 0.0022 0.0022 0.0018 0.0008
## $70K - $90K 0.0011 0.0012 0.0018 0.0009
## $90K - $110K 0.0009 0.0003 0.0006 0.0001
##
## Side Dishes Snack Foods Specialty Starchy Foods Vegetables
## $10K - $30K 0.0026 0.0234 0.0046 0.0050 0.0274
## $110K - $130K 0.0001 0.0060 0.0009 0.0013 0.0053
## $130K - $150K 0.0006 0.0059 0.0013 0.0011 0.0062
## $150K + 0.0002 0.0025 0.0004 0.0004 0.0023
## $30K - $50K 0.0038 0.0379 0.0068 0.0060 0.0392
## $50K - $70K 0.0016 0.0195 0.0036 0.0034 0.0213
## $70K - $90K 0.0016 0.0131 0.0023 0.0020 0.0153
## $90K - $110K 0.0004 0.0055 0.0007 0.0006 0.0060
## --- 3. TỶ LỆ TƯƠNG ĐỐI theo từng hàng (từng mức thu nhập) ----
prop_by_income <- round(prop.table(table_income_product, margin = 1), 4)
cat("\n>>> Tỷ lệ tương đối trong từng nhóm thu nhập:\n")
##
## >>> Tỷ lệ tương đối trong từng nhóm thu nhập:
print(prop_by_income)
##
## Baking Goods Bathroom Products Beer and Wine Bread
## $10K - $30K 0.0385 0.0275 0.0259 0.0350
## $110K - $130K 0.0280 0.0249 0.0218 0.0358
## $130K - $150K 0.0289 0.0250 0.0197 0.0316
## $150K + 0.0403 0.0293 0.0110 0.0366
## $30K - $50K 0.0328 0.0252 0.0263 0.0291
## $50K - $70K 0.0363 0.0211 0.0257 0.0266
## $70K - $90K 0.0345 0.0298 0.0228 0.0293
## $90K - $110K 0.0294 0.0326 0.0375 0.0212
##
## Breakfast Foods Candles Candy Canned Anchovies Canned Clams
## $10K - $30K 0.0359 0.0019 0.0246 0.0032 0.0039
## $110K - $130K 0.0109 0.0016 0.0249 0.0031 0.0016
## $130K - $150K 0.0368 0.0026 0.0250 0.0013 0.0039
## $150K + 0.0256 0.0037 0.0293 0.0037 0.0037
## $30K - $50K 0.0311 0.0046 0.0276 0.0030 0.0043
## $50K - $70K 0.0262 0.0030 0.0253 0.0034 0.0025
## $70K - $90K 0.0246 0.0041 0.0170 0.0035 0.0041
## $90K - $110K 0.0277 0.0000 0.0277 0.0033 0.0049
##
## Canned Oysters Canned Sardines Canned Shrimp Canned Soup
## $10K - $30K 0.0016 0.0026 0.0029 0.0317
## $110K - $130K 0.0062 0.0031 0.0000 0.0295
## $130K - $150K 0.0039 0.0013 0.0026 0.0224
## $150K + 0.0037 0.0037 0.0000 0.0293
## $30K - $50K 0.0022 0.0039 0.0035 0.0298
## $50K - $70K 0.0021 0.0021 0.0030 0.0283
## $70K - $90K 0.0029 0.0018 0.0012 0.0293
## $90K - $110K 0.0033 0.0033 0.0033 0.0131
##
## Canned Tuna Carbonated Beverages Cleaning Supplies
## $10K - $30K 0.0042 0.0117 0.0152
## $110K - $130K 0.0047 0.0093 0.0124
## $130K - $150K 0.0066 0.0039 0.0092
## $150K + 0.0110 0.0220 0.0147
## $30K - $50K 0.0061 0.0111 0.0111
## $50K - $70K 0.0080 0.0084 0.0148
## $70K - $90K 0.0059 0.0135 0.0146
## $90K - $110K 0.0098 0.0147 0.0196
##
## Cold Remedies Dairy Decongestants Drinks Eggs Electrical
## $10K - $30K 0.0074 0.0563 0.0071 0.0097 0.0120 0.0239
## $110K - $130K 0.0031 0.0591 0.0062 0.0140 0.0140 0.0311
## $130K - $150K 0.0079 0.0645 0.0066 0.0105 0.0197 0.0276
## $150K + 0.0110 0.0623 0.0000 0.0147 0.0147 0.0293
## $30K - $50K 0.0070 0.0650 0.0067 0.0100 0.0146 0.0248
## $50K - $70K 0.0051 0.0675 0.0034 0.0080 0.0152 0.0241
## $70K - $90K 0.0059 0.0737 0.0059 0.0094 0.0117 0.0275
## $90K - $110K 0.0082 0.0653 0.0082 0.0049 0.0163 0.0228
##
## Frozen Desserts Frozen Entrees Fruit Hardware Hot Beverages
## $10K - $30K 0.0243 0.0065 0.0485 0.0100 0.0155
## $110K - $130K 0.0264 0.0156 0.0451 0.0047 0.0171
## $130K - $150K 0.0224 0.0066 0.0632 0.0132 0.0118
## $150K + 0.0293 0.0073 0.0366 0.0037 0.0183
## $30K - $50K 0.0243 0.0076 0.0548 0.0089 0.0172
## $50K - $70K 0.0186 0.0089 0.0574 0.0105 0.0139
## $70K - $90K 0.0211 0.0105 0.0609 0.0076 0.0152
## $90K - $110K 0.0228 0.0114 0.0587 0.0082 0.0245
##
## Hygiene Jams and Jellies Kitchen Products Magazines Meat
## $10K - $30K 0.0117 0.0443 0.0152 0.0159 0.0505
## $110K - $130K 0.0093 0.0482 0.0078 0.0264 0.0638
## $130K - $150K 0.0184 0.0421 0.0184 0.0118 0.0684
## $150K + 0.0147 0.0293 0.0110 0.0037 0.0513
## $30K - $50K 0.0135 0.0402 0.0161 0.0141 0.0550
## $50K - $70K 0.0156 0.0435 0.0215 0.0152 0.0485
## $70K - $90K 0.0170 0.0415 0.0117 0.0105 0.0585
## $90K - $110K 0.0147 0.0343 0.0049 0.0114 0.0489
##
## Miscellaneous Packaged Vegetables Pain Relievers Paper Products
## $10K - $30K 0.0032 0.0029 0.0136 0.0227
## $110K - $130K 0.0016 0.0016 0.0109 0.0295
## $130K - $150K 0.0079 0.0013 0.0105 0.0224
## $150K + 0.0000 0.0073 0.0183 0.0293
## $30K - $50K 0.0017 0.0043 0.0133 0.0220
## $50K - $70K 0.0059 0.0034 0.0143 0.0283
## $70K - $90K 0.0012 0.0041 0.0176 0.0269
## $90K - $110K 0.0016 0.0000 0.0082 0.0277
##
## Pizza Plastic Products Pure Juice Beverages Seafood
## $10K - $30K 0.0162 0.0133 0.0110 0.0055
## $110K - $130K 0.0202 0.0093 0.0140 0.0047
## $130K - $150K 0.0158 0.0092 0.0066 0.0105
## $150K + 0.0037 0.0073 0.0183 0.0183
## $30K - $50K 0.0128 0.0072 0.0113 0.0096
## $50K - $70K 0.0131 0.0131 0.0105 0.0046
## $70K - $90K 0.0088 0.0099 0.0152 0.0070
## $90K - $110K 0.0212 0.0065 0.0147 0.0033
##
## Side Dishes Snack Foods Specialty Starchy Foods Vegetables
## $10K - $30K 0.0117 0.1065 0.0210 0.0227 0.1246
## $110K - $130K 0.0031 0.1322 0.0202 0.0280 0.1151
## $130K - $150K 0.0105 0.1092 0.0237 0.0197 0.1145
## $150K + 0.0110 0.1282 0.0183 0.0183 0.1172
## $30K - $50K 0.0115 0.1158 0.0209 0.0185 0.1198
## $50K - $70K 0.0097 0.1156 0.0211 0.0203 0.1266
## $70K - $90K 0.0135 0.1077 0.0187 0.0164 0.1258
## $90K - $110K 0.0082 0.1256 0.0163 0.0131 0.1370
Giả thuyết kiểm định:
H₀: Hai biến AnnualIncome và ProductCategory là độc lập (không có mối liên hệ)
H₁: Hai biến AnnualIncome và ProductCategory có mối liên quan (không độc lập)
# Thực hiện kiểm định Chi-squared
chi_test1 <- chisq.test(table_income_product)
## Warning in chisq.test(table_income_product): Chi-squared approximation may be
## incorrect
# Xem kết quả
chi_test1
##
## Pearson's Chi-squared test
##
## data: table_income_product
## X-squared = 295.23, df = 308, p-value = 0.6897
chi_sq_value2 <- round(chi_test1$statistic, 4)
df_value2 <- chi_test1$parameter
p_value2 <- round(chi_test1$p.value, 4)
Giá trị thống kê Chi-bình phương: 295.2279
Bậc tự do (df): 308
Giá trị p: p_value = 0.6897
Với mức ý nghĩa \(\alpha = 0.05\), vì p_value ≥ 0.05, ta không đủ cơ sở để bác bỏ giả thuyết H₀, tức là không có mối quan hệ đáng kể giữa mức thu nhập hàng năm và loại sản phẩm được mua.
Trong phân tích thống kê định lượng, bảng ngẫu nhiên (contingency table) là một công cụ cơ bản để khảo sát mối liên hệ giữa hai biến phân loại. Trong trường hợp đơn giản nhất, bảng ngẫu nhiên 2x2 biểu diễn sự phân bố của hai biến nhị phân, giúp xác định và đo lường mối liên hệ giữa chúng. Các chỉ số như hiệu tỷ lệ (risk difference), tỷ số nguy cơ (Relative Risk - RR) và tỷ số chênh (Odds Ratio - OR) đóng vai trò quan trọng trong việc lượng hóa mối quan hệ đó. Bài viết này sẽ trình bày chi tiết cấu trúc xác suất sinh ra bảng ngẫu nhiên, phương pháp so sánh hai tỷ lệ, cách xây dựng khoảng tin cậy cho Odds Ratio, và kết thúc bằng một ví dụ thực tiễn trong lĩnh vực kinh doanh.
Một bảng ngẫu nhiên 2x2 là bảng tần suất đếm số quan sát thuộc vào từng tổ hợp của hai biến nhị phân:
\[ \begin{array}{|c|c|c|c|} \hline & \text{Kết quả (+)} & \text{Kết quả (–)} & \text{Tổng} \\ \hline \text{Phơi nhiễm (Yes)} & a & b & a + b \\ \hline \text{Không phơi nhiễm (No)} & c & d & c + d \\ \hline \text{Tổng cộng} & a + c & b + d & n = a + b + c + d \\ \hline \end{array} \]
Để hiểu được sự hình thành của bảng này, cần xác định mô hình xác suất sinh ra dữ liệu — trong đó phổ biến nhất là phân phối Poisson và Multinomial.
Phân phối Poisson thường được sử dụng để mô hình hóa số lượng sự kiện xảy ra trong một khoảng thời gian, không gian hoặc đơn vị cụ thể. Giả sử các sự kiện xảy ra độc lập và với một tỷ lệ trung bình không đổi, mỗi ô trong bảng có thể xem là biến ngẫu nhiên Poisson:
\[ X_{ij} \sim \text{Poisson}(\lambda_{ij}) \]
Ưu điểm:
Phù hợp khi tổng số quan sát không cố định.
Áp dụng trong phân tích số sự kiện như: số lượt truy cập, số đơn hàng lỗi, v.v.
Hạn chế:
Trong trường hợp tổng số quan sát \(n\) là cố định, và mỗi quan sát rơi vào một trong bốn ô với xác suất \(p_1, p_2, p_3, p_4\), thì bảng ngẫu nhiên 2x2 có thể được mô hình hóa theo phân phối đa thức Multinomial như sau:
\[ (a, b, c, d) \sim \text{Multinomial}(n; p_1, p_2, p_3, p_4) \]
Phân phối này thường được sử dụng trong các tình huống mà dữ liệu được thu thập từ khảo sát hoặc nghiên cứu xã hội học với kích thước mẫu cố định. Khi đó, các xác suất \(p_1, p_2, p_3, p_4\) biểu diễn xác suất mà một cá thể rơi vào từng ô trong bảng 2x2.
Ưu điểm của mô hình Multinomial:
Kiểm soát được tổng số mẫu.
Phù hợp cho dữ liệu khảo sát, thử nghiệm.
So sánh giữa phân phối Poisson và Multinomial
Tiêu chí | Poisson | Multinomial |
---|---|---|
Tổng số mẫu | Không cố định | Cố định |
Ứng dụng chính | Số sự kiện | Tần suất khảo sát |
Dữ liệu phù hợp | Giao dịch, lỗi, tai nạn | Trả lời khảo sát, phân nhóm |
\[ RD = \frac{a}{a + b} - \frac{c}{c + d} \]
Ý nghĩa:
Đo lường chênh lệch tuyệt đối giữa xác suất xảy ra kết quả ở nhóm phơi nhiễm và nhóm không phơi nhiễm.
Thường được sử dụng trong đánh giá tác động của chính sách, can thiệp hoặc chương trình thí điểm, khi sự khác biệt về xác suất là quan trọng hơn so với tỷ số.
Khoảng tin cậy 95% (CI) cho RD có thể được ước lượng bằng:
\[ CI_{RD} = RD \pm Z_{1 - \alpha/2} \cdot SE_{RD} \]
Trong đó: - \(Z_{1 - \alpha/2}\) là giá trị tới hạn (thường ≈ 1.96 với 95% CI),
\[ RR = \frac{a / (a + b)}{c / (c + d)} \]
Ý nghĩa:
\(RR > 1\): nguy cơ xảy ra kết quả cao hơn ở nhóm phơi nhiễm.
\(RR < 1\): nguy cơ xảy ra kết quả thấp hơn ở nhóm phơi nhiễm.
\(RR = 1\): không có mối liên hệ giữa phơi nhiễm và kết quả.
Ta thường lấy log của RR để tính khoảng tin cậy:
\[ CI_{RR} = \exp \left[ \ln(RR) \pm Z_{1 - \alpha/2} \cdot SE_{\ln(RR)} \right] \]
Trong đó:
\[ SE_{\ln(RR)} = \sqrt{ \frac{1}{a} - \frac{1}{a + b} + \frac{1}{c} - \frac{1}{c + d} } \]
Ví dụ trong kinh doanh:
Tỷ lệ khách mua hàng khi có khuyến mãi: \(80/100 = 0.8\)
Khi không có khuyến mãi: \(40/100 = 0.4\)
\(RR = 0.8 / 0.4 = 2\)
⇒ Khuyến mãi làm tăng gấp đôi khả năng khách mua hàng.
Hạn chế:
⚠️ Không sử dụng được trong nghiên cứu bệnh chứng (case-control) vì ta không biết nguy cơ tuyệt đối.
⚠️ Dễ gây hiểu nhầm nếu không đi kèm nguy cơ tuyệt đối. Ví dụ: RR = 2 có vẻ cao, nhưng nếu nguy cơ ban đầu là 1%, thì tăng lên 2% vẫn là rất thấp.
⚠️ Không đối xứng: Nếu đổi nhóm tham chiếu thì giá trị RR thay đổi, khác với OR.
\[ OR = \frac{a / b}{c / d} = \frac{ad}{bc} \]
Hay
\[ \text{OR} = \frac{\text{Odds ở nhóm 1}}{\text{Odds ở nhóm 2}} \] OR thường dùng để đo lường mối liên hệ giữa một yếu tố và một kết quả trong bảng 2x2.
OR = 1: Không có sự khác biệt về odds giữa hai nhóm.
OR > 1: Nhóm 1 có odds xảy ra kết quả cao hơn nhóm 2.
OR < 1: Nhóm 1 có odds xảy ra kết quả thấp hơn nhóm 2.
Ví dụ: OR = 2 nghĩa là odds xảy ra kết quả ở nhóm 1 cao gấp 2 lần nhóm 2.
Ý nghĩa:
OR cho biết tỷ lệ odds (tức là “xác suất chia cho 1 trừ xác suất”) giữa hai nhóm.
Thường được sử dụng phổ biến trong mô hình logistic regression.
Trong các nghiên cứu bệnh hiếm (rare disease assumption), OR xấp xỉ với RR.
Ưu điểm của Odds Ratio:
Dễ tính và dễ diễn giải.
Ổn định về mặt toán học khi sử dụng trong các mô hình hồi quy.
Không phụ thuộc vào tỷ lệ hiện diện trong mẫu (đặc biệt trong các thiết kế bệnh – chứng: case-control study).
Để xác định xem OR có ý nghĩa thống kê hay không, cần xây dựng khoảng tin cậy.
Logarithm tự nhiên của Odds Ratio:
\[ \log(OR) = \log\left( \frac{a \cdot d}{b \cdot c} \right) \]
Sai số chuẩn (Standard Error):
\[ SE = \sqrt{ \frac{1}{a} + \frac{1}{b} + \frac{1}{c} + \frac{1}{d} } \]
Khoảng tin cậy 95% cho \(\log(OR)\):
\[ \log(OR) \pm 1.96 \cdot SE \]
Lấy mũ để có khoảng tin cậy 95% cho OR:
\[ CI_{95\%} = \left[ e^{\log(OR) - 1.96 \cdot SE},\quad e^{\log(OR) + 1.96 \cdot SE} \right] \]
Một công ty thương mại điện tử thử nghiệm chiến dịch khuyến mãi để kiểm tra xem liệu có ảnh hưởng đến hành vi mua hàng không. Họ lấy mẫu 200 khách hàng ngẫu nhiên và thu được bảng sau:
Mua hàng | Không mua | Tổng | |
---|---|---|---|
Có khuyến mãi | 80 | 20 | 100 |
Không khuyến mãi | 40 | 60 | 100 |
\[ OR = \frac{80 \cdot 60}{20 \cdot 40} = \frac{4800}{800} = 6 \]
→ Odds mua hàng khi có khuyến mãi cao gấp 6 lần so với khi không có khuyến mãi.
\[ \log(OR) = \log(6) \approx 1.79 \]
\[ SE = \sqrt{ \frac{1}{80} + \frac{1}{20} + \frac{1}{40} + \frac{1}{60} } \approx 0.35 \]
\[ CI = \left[ e^{1.79 - 1.96 \cdot 0.35},\quad e^{1.79 + 1.96 \cdot 0.35} \right] \approx \left[ e^{1.11},\quad e^{2.47} \right] = [3.03,\ 11.81] \]
Vì khoảng tin cậy không chứa 1, có thể kết luận rằng khuyến mãi có ảnh hưởng có ý nghĩa thống kê đến hành vi mua hàng.
Với \(OR = 6\) và \(CI = (3.03,\ 11.81)\), doanh nghiệp có thể tự tin triển khai chiến lược khuyến mãi quy mô lớn hơn.
# Bảng chéo giữa Gender và Homeowner
gh <- table(dt$Gender, dt$Homeowner)
addmargins(gh)
##
## N Y Sum
## F 2826 4344 7170
## M 2789 4100 6889
## Sum 5615 8444 14059
\[ p_1 = P(\text{Homeowner} = Y \mid \text{Gender} = F) \quad \text{(tỷ lệ nữ sở hữu nhà)} \]
\[ p_2 = P(\text{Homeowner} = Y \mid \text{Gender} = M) \quad \text{(tỷ lệ nam sở hữu nhà)} \]
Tính hiệu hai tỷ lệ:
\[ d = p_1 - p_2 \]
Kiểm định:
H₀: p₁ - p₂ = 0 (tỷ lệ nữ sở hữu nhà bằng tỷ lệ nam sở hữu nhà)
H₁: p₁ - p₂ < 0 (Tỷ lệ nữ sở hữu nhà nhỏ hơn tỷ lệ nam sở hữu nhà )
counts <- c(gh["F", "Y"], gh["M", "Y"]) # Số người sở hữu nhà theo từng giới tính
totals <- c(sum(gh["F", ]), sum(gh["M", ])) # Tổng số người theo từng giới tính
test <- prop.test(counts, totals, alternative = "less", correct = FALSE)
test
##
## 2-sample test for equality of proportions without continuity correction
##
## data: counts out of totals
## X-squared = 1.6788, df = 1, p-value = 0.9025
## alternative hypothesis: less
## 95 percent confidence interval:
## -1.00000000 0.02429777
## sample estimates:
## prop 1 prop 2
## 0.6058577 0.5951517
prop 1 (p1) = 0.6059: tỷ lệ nữ sở hữu nhà khoảng 60.59%
prop 2 (p2) = 0.5952: tỷ lệ nam sở hữu nhà khoảng 59.52%
P-value = 0.9025
Giá trị p-value thu được là 0.9025, lớn hơn mức ý nghĩa 0.05. Do đó, chúng ta không đủ bằng chứng để bác bỏ giả thuyết H₀ \(H_0: p_1 - p_2 = 0\).
Điều này có nghĩa là, theo dữ liệu hiện tại, không có sự khác biệt có ý nghĩa thống kê giữa tỷ lệ sở hữu nhà của nữ và nam, và không có bằng chứng cho thấy tỷ lệ nữ sở hữu nhà thấp hơn tỷ lệ nam.
mh <- table(dt$MaritalStatus, dt$Homeowner)
mh1 <- addmargins(mh)
print(mh1)
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
Giả thuyết kiểm định:
\[ H_0: p_1 - p_2 = 0 \quad \text{(tỷ lệ sở hữu nhà của nhóm Đã kết hôn bằng nhóm Độc thân)} \]
\[ H_1: p_1 - p_2 > 0 \quad \text{(tỷ lệ sở hữu nhà của nhóm Đã kết hôn cao hơn nhóm Độc thân)} \]
Trong đó:
- \(p_1 = P(\text{Homeowner} = Y \mid
\text{MaritalStatus} = M)\) là tỷ lệ sở hữu nhà của nhóm
Đã kết hôn (Married, M).
- \(p_2 = P(\text{Homeowner} = Y \mid
\text{MaritalStatus} = S)\) là tỷ lệ sở hữu nhà của nhóm
Độc thân (Single, S).
counts1 <- c(mh["M", "Y"], mh["S", "Y"])
totals1 <- c(sum(mh["M", ]), sum(mh["S", ]))
test1 <- prop.test(counts1, totals1, alternative = "greater", correct = FALSE)
test1
##
## 2-sample test for equality of proportions without continuity correction
##
## data: counts1 out of totals1
## X-squared = 1242.4, df = 1, p-value < 2.2e-16
## alternative hypothesis: greater
## 95 percent confidence interval:
## 0.2783377 1.0000000
## sample estimates:
## prop 1 prop 2
## 0.7496359 0.4583623
prop 1 = 0.7496: tỷ lệ sở hữu nhà của nhóm Đã kết hôn (M) là khoảng 74.96%
prop 2 = 0.4584: tỷ lệ sở hữu nhà của nhóm Độc thân (S) là khoảng 45.84%
Giá trị p-value rất nhỏ (< 2.2e-16), nhỏ hơn mức ý nghĩa 0.05, cho thấy có bằng chứng thống kê mạnh mẽ để bác bỏ giả thuyết H0. Vậy tỷ lệ sở hữu nhà của nhóm đã kết hôn nhiều hơn của nhóm độc thân.
# 1. Lập bảng chéo 2x2 giữa Gender và MaritalStatus
gm <- table(dt$Gender, dt$MaritalStatus)
addmargins(gm) # Thêm hàng và cột tổng
##
## M S Sum
## F 3602 3568 7170
## M 3264 3625 6889
## Sum 6866 7193 14059
Giả thuyết kiểm định
\[ H_0: p_1 - p_2 = 0 \quad \text{(Tỷ lệ đã kết hôn của nữ bằng nam)} \]
\[ H_1: p_1 - p_2 > 0 \quad \text{(Tỷ lệ đã kết hôn của nữ lớn hơn nam)} \]
Trong đó: - \(p_1 = P(\text{MaritalStatus} = M \mid \text{Gender} = F)\): tỷ lệ nữ đã kết hôn
# Trích số lượng người đã kết hôn theo giới
counts3 <- c(gm["F", "M"], gm["M", "M"])
totals3 <- c(sum(gm["F", ]), sum(gm["M", ]))
# Thực hiện kiểm định hiệu hai tỷ lệ
test3 <- prop.test(counts3, totals3, alternative = "greater", correct = FALSE)
test3
##
## 2-sample test for equality of proportions without continuity correction
##
## data: counts3 out of totals3
## X-squared = 11.479, df = 1, p-value = 0.0003519
## alternative hypothesis: greater
## 95 percent confidence interval:
## 0.01470685 1.00000000
## sample estimates:
## prop 1 prop 2
## 0.5023710 0.4737988
Kết quả kiểm định cho thấy:
Tỷ lệ nữ đã kết hôn (\(p_1\)) ≈ 50.24%
Tỷ lệ nam đã kết hôn (\(p_2\)) ≈ 47.38%
Hiệu hai tỷ lệ: \(d = p_1 - p_2 \approx 0.0286\)
Giá trị p-value = 0.00035
Khoảng tin cậy 95% cho hiệu tỷ lệ: [0.0147; 1]
Vì p-value < 0.05, ta bác bỏ giả thuyết \(H_0\). Điều này cho thấy có bằng chứng thống kê để kết luận rằng: Tỷ lệ nữ đã kết hôn cao hơn tỷ lệ nam đã kết hôn trong tập dữ liệu khảo sát.
gh <- table(dt$Gender, dt$Homeowner)
#Thêm tổng hàng và cột
gh1 <- addmargins(gh)
gh1
##
## N Y Sum
## F 2826 4344 7170
## M 2789 4100 6889
## Sum 5615 8444 14059
riskratio(gh, 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"
Nhóm nữ (F) được chọn làm nhóm tham chiếu, nên RR = 1. Điều này có nghĩa chúng ta so sánh nguy cơ sở hữu nhà của nhóm nam (M) với nhóm nữ.
Nhóm nam (M) có RR = 0.9823 nghĩa là:
` - Hay nói cách khác, nguy cơ (xác suất) sở hữu nhà của nam thấp hơn nữ khoảng 1.77%.
Khoảng tin cậy 95% của RR là (0.9562 – 1.0092):
Khoảng này bao gồm số 1, nghĩa là giá trị RR thực sự có thể là 1 (không có khác biệt).
Khoảng tin cậy cho ta biết mức độ chính xác của ước lượng RR; khoảng rộng và bao gồm 1 cho thấy sự không chắc chắn và thiếu bằng chứng về sự khác biệt thực sự.
Ta có giả thuyết:
H₀: Tỷ lệ sở hữu nhà ở Nam và Nữ không khác nhau, tức là RR = 1.
H₁: Tỷ lệ sở hữu nhà ở Nam và Nữ khác nhau, RR ≠ 1.
Kiểm định | p-value (Nam so với Nữ) | Ý nghĩa chính |
---|---|---|
midp.exact | 0.1952 | p-value chính xác, sử dụng phương pháp “mid-p” (một biến thể chính xác hơn Fisher) |
fisher.exact | 0.1965 | p-value từ kiểm định Fisher chính xác (phù hợp với bảng nhỏ hoặc số liệu ít) |
chi.square | 0.1951 | p-value từ kiểm định Chi-square (xấp xỉ, dựa trên phân phối chi bình phương) |
Vì p-value > 0.05, ta không có đủ bằng chứng để nói rằng giới tính ảnh hưởng đáng kể đến khả năng sở hữu nhà.
Nói cách khác, sự khác biệt giữa nhóm Nam và nhóm Nữ về tỷ lệ sở hữu nhà không có ý nghĩa thống kê.
mh <- table(dt$MaritalStatus, dt$Homeowner)
mh1 <- addmargins(mh)
print(mh1)
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
riskratio(mh)
## $data
##
## N Y Total
## M 1719 5147 6866
## S 3896 3297 7193
## Total 5615 8444 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## M 1.0000000 NA NA
## S 0.6114466 0.5942071 0.6291862
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## M NA NA NA
## S 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 (M) được dùng làm nhóm tham chiếu với RR = 1.
Nhóm độc thân (S) có:
RR = 0.6114 (khoảng tin cậy 95%: 0.5942 – 0.6292).
Điều này có nghĩa là người độc thân có nguy cơ sở hữu nhà thấp hơn khoảng 38.86% so với người đã kết hôn.
Khoảng tin cậy 95% khá hẹp và không bao gồm giá trị 1, cho thấy sự khác biệt này là rõ ràng và đáng tin cậy.
Ta thực hiện kiểm định giả thuyết như sau:
H₀: Tỷ lệ sở hữu nhà của người đã kết hôn và độc thân là như nhau (RR = 1).
H₁: Tỷ lệ sở hữu nhà của hai nhóm là khác nhau (RR ≠ 1).
Kết quả phân tích chỉ ra RR = 0.6114 với khoảng tin cậy 95% (0.5942 – 0.6292), và các kiểm định cho p-value ≈ 0 < mức ý nghĩa 0.05. Do đó, ta bác bỏ H₀ và kết luận rằng tình trạng hôn nhân có mối liên hệ thống kê rõ rệt với khả năng sở hữu nhà. Người độc thân có khả năng sở hữu nhà thấp hơn đáng kể so với người đã kết hôn.
# 1. Lập bảng chéo 2x2 giữa Gender và MaritalStatus
gm <- table(dt$Gender, dt$MaritalStatus)
addmargins(gm) # Thêm hàng và cột tổng
##
## M S Sum
## F 3602 3568 7170
## M 3264 3625 6889
## Sum 6866 7193 14059
# 3. Tính RR
riskratio(gm)
## $data
##
## M S Total
## F 3602 3568 7170
## M 3264 3625 6889
## Total 6866 7193 14059
##
## $measure
## risk ratio with 95% C.I.
## estimate lower upper
## F 1.000000 NA NA
## M 1.057417 1.023813 1.092123
##
## $p.value
## two-sided
## midp.exact fisher.exact chi.square
## F NA NA NA
## M 0.0007045092 0.0007373895 0.0007038837
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
Nam giới có nguy cơ đã kết hôn cao hơn nữ giới khoảng 5.7%. Vì RR > 1, điều này cho thấy tỷ lệ kết hôn ở nam cao hơn nữ trong dữ liệu này.
Với p-value < 0.05 và khoảng tin cậy không chứa 1, chúng ta có
bằng chứng thống kê để bác bỏ giả thuyết không.
Như vậy, nam giới có tỷ lệ kết hôn cao hơn nữ giới
trong bộ dữ liệu này.
# Tính OR và khoảng tin cậy
or_gh <- OddsRatio(gh, method = "wald", conf.level = 0.95)
or_gh
## odds ratio lwr.ci upr.ci
## 0.9563518 0.8939173 1.0231469
Kết quả phân tích Odds Ratio giữa giới tính và khả năng sở hữu nhà như sau:
Odds Ratio (OR) = 0.956
Khoảng tin cậy 95%: từ 0.894 đến 1.023
Diễn giải:
Giá trị OR = 0.956 cho thấy odds (cơ hội) sở hữu nhà của nữ thấp hơn nam khoảng 4.4%. Tuy nhiên, sự khác biệt là nhỏ.
Do khoảng tin cậy 95% chứa giá trị 1, nên:
Kết luận: Mặc dù nữ có vẻ có odds sở hữu nhà thấp hơn nam một chút, nhưng sự khác biệt không có ý nghĩa thống kê. Do đó, giới tính không phải là yếu tố ảnh hưởng rõ rệt đến khả năng sở hữu nhà trong dữ liệu hiện tại.
# Tính OR và khoảng tin cậy
or_mh <- OddsRatio(mh, method = "wald", conf.level = 0.95)
or_mh
## odds ratio lwr.ci upr.ci
## 0.2826322 0.2630929 0.3036227
Odds Ratio (OR) = 0.283
Khoảng tin cậy 95%: từ 0.263 đến 0.304
Diễn giải:
Giá trị Odds Ratio 0.283 có nghĩa là odds sở hữu nhà của nhóm người độc thân chỉ bằng khoảng 28.3% odds của nhóm người đã kết hôn. Nói cách khác, người đã kết hôn có khả năng sở hữu nhà cao hơn gần 3.5 lần so với người độc thân (vì 1/0.283≈3.53).
Khoảng tin cậy 95% cho Odds Ratio nằm hoàn toàn dưới 1, từ 0.263 đến 0.304, điều này cho thấy sự khác biệt về odds sở hữu nhà giữa hai nhóm là có ý nghĩa thống kê và không phải do ngẫu nhiên.
Kết luận:
Dữ liệu cho thấy tình trạng hôn nhân ảnh hưởng rõ ràng đến khả năng sở hữu nhà. Người đã kết hôn có odds sở hữu nhà cao hơn đáng kể so với người độc thân, và khác biệt này là có ý nghĩa thống kê với mức độ tin cậy 95%. Đây là bằng chứng cho thấy việc đã kết hôn có liên quan chặt chẽ đến khả năng sở hữu nhà trong mẫu khảo sát này.
# Tính OR và khoảng tin cậy
or_gm <- OddsRatio(gm, method = "wald", conf.level = 0.95)
or_gm
## odds ratio lwr.ci upr.ci
## 1.121184 1.049386 1.197893
Odds Ratio (OR) = 1.121
Khoảng tin cậy 95%: từ 1.049 đến 1.198
Diễn giải:
Giá trị Odds Ratio 1.121 có nghĩa là odds (cơ hội) đã kết hôn của nữ cao hơn odds đã kết hôn của nam khoảng 12.1%, hay nói cách khác, nữ có khả năng đã kết hôn cao hơn nam khoảng 1.12 lần.
Khoảng tin cậy 95% từ 1.049 đến 1.198, không chứa giá trị 1, chứng tỏ sự khác biệt này là có ý nghĩa thống kê. Điều này nghĩa là với mức tin cậy 95%, chúng ta chắc chắn rằng tỷ lệ đã kết hôn của nữ và nam không bằng nhau.
Kết luận:
Dữ liệu cho thấy nữ giới có odds đã kết hôn cao hơn nam giới khoảng 12%, tương đương với việc nữ có khả năng đã kết hôn gấp 1.12 lần so với nam giới.
Dựa trên các phân tích định tính từ bộ dữ liệu 14,059 giao dịch siêu thị, một số đặc điểm nổi bật của khách hàng và hành vi mua sắm có thể rút ra như sau:
Cơ cấu giới tính và tình trạng hôn nhân:
Khách hàng nữ chiếm ưu thế nhẹ (~51%), với sự chênh lệch không lớn so với nam (~49%).
Người độc thân (S) và người đã kết hôn (M) có tỷ lệ gần tương đương, nhưng có sự khác biệt rõ rệt về hành vi sở hữu nhà.
Tình trạng sở hữu nhà:
Khoảng 60% khách hàng sở hữu nhà, cho thấy phần lớn là nhóm ổn định về kinh tế và chỗ ở.
Có mối quan hệ đáng kể giữa MaritalStatus và Homeowner: Người đã kết hôn có xu hướng sở hữu nhà nhiều hơn đáng kể (74.96%) so với người độc thân (45.84%).
Phân bố thu nhập:
Nhóm $30K - $50K chiếm tỷ lệ cao nhất (32.73%), cho thấy khách hàng chủ yếu thuộc tầng lớp trung lưu.
Các nhóm thu nhập cao ($150K+) rất ít (~2%), có thể do thị phần hoặc hành vi mua sắm khác biệt.
Địa lý:
Các giao dịch chủ yếu đến từ USA (68%), đặc biệt là các bang WA, CA, OR.
Các thành phố nổi bật gồm Salem, Tacoma, Los Angeles, chiếm tỷ trọng lớn trong tổng số giao dịch.
Hành vi mua sắm theo sản phẩm:
Thực phẩm (Food) là nhóm sản phẩm chính (72.2%), đặc biệt là:
Vegetables (12.29%)
Snack Foods (11.38%)
Dairy (6.42%)
Các sản phẩm không tiêu thụ được (Non-consumable) chiếm ~19%, và Drink chiếm khoảng 9%.
Phân tích trong báo cáo này chủ yếu tập trung vào các biến định tính và do đó còn một số hạn chế như sau:
Thứ nhất, phân tích chủ yếu tập trung vào các biến định tính như Gender, MaritalStatus, Homeowner, AnnualIncome (dưới dạng phân nhóm), City, ProductFamily và ProductCategory. Việc không đưa vào các biến định lượng như tuổi tác, thu nhập cụ thể (theo số), tổng mức chi tiêu, số lượng giao dịch hay tần suất mua hàng đã làm giảm độ sâu và tính định lượng của các kết luận. Những yếu tố này có thể giúp xác định rõ hơn mối quan hệ giữa đặc điểm khách hàng và hành vi tiêu dùng.
Thứ hai, dữ liệu có thể không cân bằng giữa các nhóm, dẫn đến sai lệch trong kết luận. Ví dụ, nhóm thu nhập rất cao hoặc một số thành phố có số lượng quan sát rất nhỏ so với toàn bộ tập dữ liệu, làm giảm tính đại diện và khả năng khái quát hóa. Việc so sánh các nhóm có quy mô khác biệt mà không điều chỉnh trọng số có thể gây hiểu lầm về mức độ ảnh hưởng của từng đặc điểm nhân khẩu học đến hành vi tiêu dùng.
Thứ ba, các biến được phân tích có khả năng tương quan lẫn nhau – ví dụ như thu nhập và tình trạng sở hữu nhà, hoặc thu nhập và nơi cư trú – nhưng bài phân tích chưa đánh giá các mối quan hệ chéo này. Việc không kiểm soát ảnh hưởng chéo giữa các biến khiến cho kết luận về tác động riêng lẻ của từng yếu tố có thể chưa hoàn toàn chính xác.
Thứ tư, yếu tố giới tính (Gender) tuy được thống kê nhưng chưa được phân tích sâu liên quan đến hành vi tiêu dùng như ưu tiên sản phẩm, mức độ chi tiêu hoặc khác biệt trong lựa chọn theo giới. Trong thực tế, giới tính thường ảnh hưởng đáng kể đến hành vi mua sắm và sở thích tiêu dùng, nên việc không khai thác kỹ khía cạnh này là một điểm thiếu sót đáng kể.
Dựa trên các phân tích đã thực hiện, một số đề xuất chiến lược dành cho doanh nghiệp như sau:
Tập trung vào phân khúc chủ lực:
Thiết kế chương trình chăm sóc riêng cho nhóm đã kết hôn sở hữu nhà:
Tái cấu trúc trưng bày sản phẩm và quản lý tồn kho:
Tăng diện tích cho các nhóm sản phẩm bán chạy như Vegetables, Snack Foods, Dairy.
Rà soát các danh mục có tần suất thấp (như Canned Oysters, Candles) để tối ưu không gian và dòng tiền.
Phát triển thị trường theo khu vực địa lý:
Khuyến khích mở rộng dữ liệu trong tương lai:
Liệu nhóm khách hàng độc thân nhưng có thu nhập cao và sở hữu nhà có hành vi chi tiêu gần giống với nhóm đã kết hôn và thu nhập cao hay không?
→ So sánh hai nhóm có điểm chung về thu nhập và sở hữu nhà nhưng khác tình trạng hôn nhân.
Sự kết hợp giữa tình trạng hôn nhân và độ tuổi (nếu có) ảnh hưởng thế nào đến việc lựa chọn nhóm sản phẩm?
→ Ví dụ: Người trẻ đã kết hôn có tiêu dùng khác với người lớn tuổi đã kết hôn?
Khách hàng sống tại các khu vực đô thị có xu hướng chi tiêu nhiều hơn cho sản phẩm tiện lợi so với khách hàng nông thôn không?
→ Phân tích theo biến địa lý hoặc thành phố.
Những nhóm nhân khẩu học nào chi tiêu cao nhất cho nhóm sản phẩm không tiêu dùng được (Non-consumable)?
→ Ví dụ: Có phải người độc thân, không có nhà, thu nhập cao quan tâm nhiều hơn đến sản phẩm phi thực phẩm?
Có sự thay đổi nào trong tỷ trọng chi tiêu giữa các nhóm thu nhập đối với từng danh mục sản phẩm chính (Produce, Dairy, Snack Foods, v.v.)?
→ Phân tích tỷ lệ chi tiêu từng loại theo từng mức thu nhập.