data <- read.csv("C:/Users/Ngo Trang/Documents/Supermarket Transactions.csv", header = TRUE)
str(data)
## '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 ...
Bộ dữ liệu data gồm 14,059 quan sát với 16 biến, ghi lại các giao dịch mua hàng của khách hàng cùng thông tin liên quan đến đặc điểm cá nhân và sản phẩm.
Giới tính - Gender, Tình trạng hôn nhân - MaritalStatus, Sở hữu nhà - Homeowner, Khoảng thu nhập hàng năm - AnnualIncome, Thành phố - City, Bang/Tỉnh - StateorProvince, Quốc gia - Country, Nhóm sản phẩm - ProductFamily, Bộ phận sản phẩm - ProductDepartment, Danh mục sản phẩm - ProductCategory.
Số thứ tự bản ghi - X, mã khách hàng - CustomerID,Số lượng con trong gia đình - Children, số lượng sản phẩm bán ra trong mỗi giao dịch - UnitsSold, Doanh thu từ mỗi giao dịch - Revenue.
Để phục vụ cho việc phân tích đặc điểm phân loại của khách hàng và sản phẩm, ta lựa chọn các biến định tính bao gồm Gender, MaritalStatus, Homeowner, AnnualIncome, City, StateorProvince, Country, ProductFamily, ProductDepartment, ProductCategory. Các biến này được lưu trong vector bdt.
bdt <- c("Gender","MaritalStatus","Homeowner","AnnualIncome","City","StateorProvince", "Country","ProductFamily","ProductDepartment", "ProductCategory")
Việc tập trung vào các biến định tính này giúp thuận tiện cho các phân tích phân nhóm, bảng tần số và trực quan hóa nhằm hiểu rõ hơn về đặc điểm khách hàng và phân bố sản phẩm.
d <- data[ ,bdt]
str(d)
## 'data.frame': 14059 obs. of 10 variables:
## $ Gender : chr "F" "M" "F" "M" ...
## $ MaritalStatus : chr "S" "M" "M" "M" ...
## $ Homeowner : chr "Y" "Y" "N" "Y" ...
## $ 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" ...
Bộ dữ liệu d gồm 14,059 quan sát với 10 biến định tính là bộ dữ liệu được trích từ bộ dữ liệu lớn data phản ánh các đặc điểm nhân khẩu học của khách hàng, vị trí địa lý và phân loại sản phẩm trong các giao dịch mua hàng. Cụ thể các biến bao gồm:
- Thông tin khách hàng:
Gender: Giới tính (ví dụ: “F” – nữ, “M” – nam)
MaritalStatus: Tình trạng hôn nhân (ví dụ: “S” – độc thân, “M” – đã kết hôn)
Homeowner: Tình trạng sở hữu nhà (ví dụ: “Y” – có nhà, “N” – không có nhà)
AnnualIncome: Khoảng thu nhập hàng năm (ví dụ: “$30K - $50K”, “$70K - $90K”)
- Thông tin địa lý:
City: Thành phố cư trú
StateorProvince: Bang hoặc tỉnh thành
Country: Quốc gia
- Phân loại sản phẩm:
ProductFamily: Nhóm sản phẩm chính (ví dụ: “Food”)
ProductDepartment: Bộ phận sản phẩm cụ thể hơn (ví dụ: “Snack Foods”)
ProductCategory: Danh mục sản phẩm chi tiết (ví dụ: “Candy”)
Để khám phá dữ liệu ban đầu chúng ta sẽ xem nhanh cấu trúc và nội dung dữ liệu ở 5 quan sát đầu và 5 quan sát cuối bảng
# Hiển thị một vài dòng đầu của dữ liệu
head(d,5)
# Hiển thị một vài dòng cuối của dữ liệu
tail(d,5)
Trước khi tiến hành phân tích, chúng ta cần kiểm tra xem dữ liệu có chứa giá trị thiếu (NA) hay không. Việc này rất quan trọng để đảm bảo chất lượng dữ liệu, tránh sai lệch hoặc lỗi trong quá trình xử lý và phân tích sau này. Câu lệnh sau được sử dụng để kiểm tra tổng số giá trị thiếu trong toàn bộ bảng dữ liệu:
# Kiểm tra sự tồn tại của biến NA
sum(is.na(d))
## [1] 0
Dựa vào kết quả, cho thấy dữ liệu không chứa giá trị thiếu, do đó ta có thể yên tâm tiếp tục phân tích mà không cần xử lý dữ liệu bị thiếu.
1. Thống kê Tần suất
ge1 <- table(d$Gender)
ge1
##
## F M
## 7170 6889
Vậy trong bộ dữ liệu này có 7170 nữ và 3688 nam.
# Lập bảng tần suất
ge2 <- table(d$Gender)/sum(nrow(d))
ge2
##
## F M
## 0.5099936 0.4900064
Vậy trong bộ dữ liệu này có 50.9993598 % người là nữ và 49.0006402 % người là nam.
2. Trực quan hóa
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(ggplot2)
ggplot(d %>% count(Gender), aes(x = Gender, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(ge2[Gender] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Đồ thị thống kê theo giới tính",
x = "Giới tính",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(ge2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ giới tính", fill = "Giới tính") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Dữ liệu gồm 14,059 khách hàng, trong đó nữ chiếm 7,170 người (khoảng 51%), nam chiếm 6,889 người (khoảng 49%). Tỷ lệ này khá cân bằng, cho thấy phân bố giới tính đồng đều trong tập dữ liệu. Điều này giúp đảm bảo tính đại diện khi phân tích hành vi theo giới, đồng thời cho phép so sánh giữa hai nhóm mà không lo bị lệch mẫu.
1. Thống kê Tần suất
ma1 <- table(d$MaritalStatus)
ma1
##
## M S
## 6866 7193
Vậy trong bộ dữ liệu này có 6866 người đã kết hôn và có 7193 người chưa kết hôn.
# Lập bảng tần suất
ma2 <- table(d$MaritalStatus)/sum(nrow(d))
ma2
##
## M S
## 0.4883704 0.5116296
Vậy trong bộ dữ liệu này có 48.8370439 % người đã kết hôn và có 51.1629561 % người chưa kết hôn.
2. Trực quan hóa
ggplot(d %>% count(MaritalStatus), aes(x = MaritalStatus, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(ma2[MaritalStatus] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Đồ thị thống kê theo tình trạng hôn nhân",
x = "Tình trạng hôn nhân",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(ma2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ tình trạng hôn nhân", fill = "Tình trạng hôn nhân") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Trong tổng số 14,059 khách hàng, có 7,193 người độc thân (S) chiếm khoảng 51.16%, và 6,866 người đã kết hôn (M) chiếm khoảng 48.84%. Sự phân bố giữa hai nhóm khá đồng đều, với nhóm độc thân nhỉnh hơn một chút. Điều này cho phép so sánh hành vi giữa hai nhóm mà không lo mất cân đối mẫu, đồng thời gợi ý rằng doanh nghiệp nên cân nhắc các chiến lược tiếp cận phù hợp theo tình trạng hôn nhân.
1. Thống kê Tần suất
ho1 <- table(d$Homeowner)
ho1
##
## N Y
## 5615 8444
Vậy trong bộ dữ liệu này có 5615 người chưa sở hữu nhà và có 8444 người đã sở hữu nhà.
# Lập bảng tần suất
ho2 <- table(d$Homeowner)/sum(nrow(d))
ho2
##
## N Y
## 0.3993883 0.6006117
Vậy trong bộ dữ liệu này có 39.9388292 % người chưa sở hữu nhà và có 60.0611708 % người đã sở hữu nhà.
2. Trực quan hóa
ggplot(d %>% count(Homeowner), aes(x = Homeowner, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(ho2[Homeowner] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Đồ thị thống kê số lượng người sở hữu nhà",
x = "Tình trạng sở hữu nhà",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(ho2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ người sở hữu nhà", fill = "Tình trạng sở hữu nhà") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Trong số 14,059 khách hàng, có 8,444 người sở hữu nhà (Y), chiếm khoảng 60.06%, trong khi 5,615 người không sở hữu nhà (N), chiếm khoảng 39.94%. Sự chênh lệch khá rõ ràng cho thấy phần lớn khách hàng là chủ sở hữu nhà, điều này có thể phản ánh mức độ ổn định tài chính cao hơn và là yếu tố quan trọng để doanh nghiệp cân nhắc khi xây dựng các chiến lược tiếp thị hoặc phân khúc khách hàng.
1. Thống kê Tần suất
an1 <- table(d$AnnualIncome)
an1
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 3090 643 760 273 4601
## $50K - $70K $70K - $90K $90K - $110K
## 2370 1709 613
Vậy trong bộ dữ liệu này có:
3090 người có thu nhập $10K - $30K,
643 người có thu nhập $110K - $130K,
760 người có thu nhập $130K - $150K,
273 người có thu nhập $150K +,
4601 người có thu nhập $30K - $50K,
2370 người có thu nhập $50K - $70K,
1709 người có thu nhập $70K - $90K,
613 người có thu nhập $90K - $110K.
# Lập bảng tần suất
an2 <- table(d$AnnualIncome)/sum(nrow(d))
an2
##
## $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
Vậy trong bộ dữ liệu này có:
21.9788036 % người có thu nhập $10K - $30K.
4.5735828 % người có thu nhập $110K - $130K.
5.4057899 % người có thu nhập $130K - $150K.
1.9418166 % người có thu nhập $150K +.
32.7263675 % người có thu nhập $30K - $50K.
16.857529 % người có thu nhập $50K - $70K.
12.1559144 % người có thu nhập $70K - $90K.
4.3601963 % người có thu nhập $90K - $110K.
2. Trực quan hóa
ggplot(d %>% count(AnnualIncome), aes(x = AnnualIncome, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(an2[AnnualIncome] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Đồ thị thống kê mức thu nhập",
x = "Mức thu nhập",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(an2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ mức thu nhập", fill = "Mức thu nhập") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Biến AnnualIncome thể hiện thu nhập hàng năm của khách hàng được phân thành nhiều nhóm. Phân bố cho thấy nhóm đông nhất là “$30K - $50K” với 4,601 người (32.73%), tiếp theo là “$10K - $30K” (3,090 người, 21.98%) và “$50K - $70K” (2,370 người, 16.86%). Ngược lại, các nhóm thu nhập cao như “$150K+” và “$130K - $150K” chỉ chiếm lần lượt 1.94% và 5.41%.
Điều này cho thấy phần lớn khách hàng thuộc nhóm thu nhập trung bình – thấp, gợi ý rằng doanh nghiệp nên tập trung phát triển các dòng sản phẩm có giá cả hợp lý hoặc chương trình khuyến mãi hướng đến nhóm thu nhập phổ thông để tối ưu hiệu quả tiếp cận.
1. Thống kê tần suất
# Lập bảng tần số
ci1 <- table(d$City)
ci1
##
## Acapulco Bellingham Beverly Hills Bremerton Camacho
## 383 143 811 834 452
## Guadalajara Hidalgo Los Angeles Merida Mexico City
## 75 845 926 654 194
## Orizaba Portland Salem San Andres San Diego
## 464 876 1386 621 866
## San Francisco Seattle Spokane Tacoma Vancouver
## 130 922 875 1257 633
## Victoria Walla Walla Yakima
## 176 160 376
Vậy trong bộ dữ liệu này có:
383 người ở thành phố Acapulco.
143 người ở thành phố Bellingham.
811 người ở thành phố Beverly Hills.
834 người ở thành phố Bremerton.
452 người ở thành phố Camacho.
75 người ở thành phố Guadalajara.
845 người ở thành phố Hidalgo.
926 người ở thành phố Los Angeles.
654 người ở thành phố Merida.
194 người ở thành phố Mexico City.
464 người ở thành phố Orizaba.
876 người ở thành phố Portland.
1386 người ở thành phố Salem.
621 người ở thành phố San Andres.
866 người ở thành phố San Diego.
130 người ở thành phố San Francisco.
922 người ở thành phố Seattle.
875 người ở thành phố Spokane.
1257 người ở thành phố Tacoma.
633 người ở thành phố Vancouver.
176 người ở thành phố Victoria.
160 người ở thành phố Walla Walla.
376 người ở thành phố Yakima.
# Lập bảng tần suất
ci2 <- table(d$City)/sum(nrow(d))
ci2
##
## 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
Vậy trong bộ dữ liệu này có:
2.7242336 % người ở thành phố Acapulco.
1.017142 % người ở thành phố Bellingham.
5.7685468 % người ở thành phố Beverly Hills.
5.9321431 % người ở thành phố Bremerton.
3.2150224 % người ở thành phố Camacho.
0.5334661 % người ở thành phố Guadalajara.
6.0103848 % người ở thành phố Hidalgo.
6.5865282 % người ở thành phố Los Angeles.
4.6518245 % người ở thành phố Merida.
1.379899 % người ở thành phố Mexico City.
3.300377 % người ở thành phố Orizaba.
6.2308841 % người ở thành phố Portland.
9.8584537 % người ở thành phố Salem.
4.4170994 % người ở thành phố San Andres.
6.1597553 % người ở thành phố San Diego.
0.9246746 % người ở thành phố San Francisco.
6.5580767 % người ở thành phố Seattle.
6.2237712 % người ở thành phố Spokane.
8.940892 % người ở thành phố Tacoma.
4.5024539 % người ở thành phố Vancouver.
1.2518671 % người ở thành phố Victoria.
1.138061 % người ở thành phố Walla Walla.
2.6744434 % người ở thành phố Yakima.
2. Trực quan hóa
ggplot(data = as.data.frame(ci1), aes(x = Freq, y = reorder(Var1, Freq))) +
geom_col(fill = "steelblue") +
geom_text(aes(label = paste0(Freq, " (", round(ci2[Var1] * 100, 1), "%)")),
hjust = -0.1, color = "black") +
labs(title = "Số dân cư tại các Thành phố", x = "Số lượng", y = "Thành phố") +
theme_minimal() +
xlim(0, max(ci1) * 1.2)
Nhận xét:
Biến City gồm nhiều thành phố với sự phân bố khách hàng không đồng đều. Thành phố có số lượng khách hàng lớn nhất là Salem với 1,386 người (khoảng 9.86%), tiếp theo là Tacoma (1,257; 8.94%) và Los Angeles (926; 6.59%). Các thành phố nhỏ hơn như Guadalajara (75; 0.53%) và Mexico City (194; 1.38%) chiếm tỷ lệ khá nhỏ trong tổng số.
Điều này cho thấy tập dữ liệu tập trung chủ yếu ở một số thành phố lớn, phản ánh mức độ hoạt động hoặc thị trường tiêu thụ chính tại những khu vực này. Doanh nghiệp có thể cân nhắc tập trung chiến lược marketing hoặc mở rộng phân phối tại các thành phố có lượng khách hàng lớn để tối ưu hiệu quả kinh doanh.
1. Thống kê Tần suất
st1 <- table(d$StateorProvince)
st1
##
## BC CA DF Guerrero Jalisco OR Veracruz WA
## 809 2733 815 383 75 2262 464 4567
## Yucatan Zacatecas
## 654 1297
Vậy trong bộ dữ liệu này có 809 người ở tỉnh BC.
2733 người ở tỉnh CA.
815 người ở tỉnh DF.
383 người ở tỉnh Guerrero.
75 người ở tỉnh Jalisco.
2262 người ở tỉnh OR.
464 người ở tỉnh Veracruz.
4567 người ở tỉnh WA.
654 người ở tỉnh Yucatan.
1297 người ở tỉnh Zacatecas.
# Lập bảng tần suất
st2 <- table(d$StateorProvince)/sum(nrow(d))
st2
##
## 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
Vậy trong bộ dữ liệu này có:
5.7543211 % người ở tỉnh BC.
19.4395049 % người ở tỉnh CA.
5.7969984 % người ở tỉnh DF.
2.7242336 % người ở tỉnh Guerrero.
0.5334661 % người ở tỉnh Jalisco.
16.0893378 % người ở tỉnh OR.
3.300377 % người ở tỉnh Veracruz.
32.4845295 % người ở tỉnh WA.
4.6518245 % người ở tỉnh Yucatan.
9.2254072 % người ở tỉnh Zacatecas.
2. Trực quan hóa
ggplot(d %>% count(StateorProvince), aes(x = StateorProvince, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(st2[StateorProvince] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Số dân cư tại các tỉnh thành",
x = "Tỉnh thành",
y = "Số lượng") +
theme_minimal()
Nhận xét:
Biến StateorProvince ghi nhận số lượng khách hàng phân bổ tại các tỉnh/thành khác nhau. Trong tổng số 14,059 quan sát, các tỉnh như WA (Washington) chiếm tỷ lệ cao nhất với 4,567 khách hàng (khoảng 32.5%), tiếp theo là CA (California) với 2,733 khách hàng (19.4%) và OR (Oregon) với 2,262 khách hàng (16.1%). Các tỉnh khác như Zacatecas (1,297 khách, 9.2%), BC (809 khách, 5.8%) và DF (815 khách, 5.8%) cũng có sự đóng góp đáng kể. Một số tỉnh có số lượng quan sát thấp hơn như Jalisco chỉ với 75 khách (0.53%), cho thấy sự phân bố không đồng đều giữa các khu vực.
1. Thống kê Tần suất
co1 <- table(d$Country)
co1
##
## Canada Mexico USA
## 809 3688 9562
Vậy trong bộ dữ liệu này có 809 người ở quốc gia Canada.
3688 người ở quốc gia Mexico.
9562 người ở quốc gia USA.
# Lập bảng tần suất
co2 <- table(d$Country)/sum(nrow(d))
co2
##
## Canada Mexico USA
## 0.05754321 0.26232307 0.68013372
Vậy trong bộ dữ liệu này có 5.7543211 % người ở quốc gia Canada.
26.2323067 % người ở quốc gia Mexico.
68.0133722 % người ở quốc gia USA.
2. Trực quan hóa
ggplot(d %>% count(Country), aes(x = Country, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(co2[Country] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Số dân cư tại các quốc gia",
x = "quốc gia",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(co2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ dân cư tại các quốc gia", fill = "Quốc gia") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Biến Country thể hiện phân bố khách hàng theo quốc gia. Trong tổng số 14,059 quan sát, phần lớn khách hàng đến từ USA với 9,562 người, chiếm tỷ lệ 68.0%. Tiếp theo là Mexico với 3,688 khách hàng, chiếm khoảng 26.2%, và cuối cùng là Canada với 809 khách hàng, chiếm 5.8%. Dữ liệu cho thấy thị trường chính tập trung chủ yếu ở Mỹ và Mexico, trong khi Canada chiếm một phần nhỏ hơn đáng kể.
1. Thống kê tần suất
# Lập bảng tần số
fa1 <- table(d$ProductFamily)
fa1
##
## Drink Food Non-Consumable
## 1250 10153 2656
Vậy trong bộ dữ liệu này có 1250 là đồ uống.
10153 là thực phẩm.
2656 là thực phẩm không tiêu dùng trực tiếp.
# Lập bảng tần suất
fa2 <- table(d$ProductFamily)/sum(nrow(d))
fa2
##
## Drink Food Non-Consumable
## 0.08891102 0.72217085 0.18891813
Vậy trong bộ dữ liệu này có:
8.8911018 % là đồ uống.
72.2170851 % là thực phẩm.
18.8918131 % là thực phẩm không tiêu dùng trực tiếp.
3. Trực quan hóa
ggplot(d %>% count(ProductFamily), aes(x = ProductFamily, y = n)) +
geom_col(fill = 'skyblue') +
geom_text(aes(label = paste0(n, " (", round(fa2[ProductFamily] * 100, 1), "%)")),
vjust = -0.5, color = 'black') +
labs(title = "Số lượng các dòng sản phẩm được sử dụng",
x = "Dòng sản phẩm",
y = "Số lượng") +
theme_minimal()
ggplot(as.data.frame(fa2), aes(x = "", y = Freq, fill = Var1)) +
geom_col(width = 1, color = "white") +
coord_polar("y") +
geom_text(aes(label = paste0(round(Freq * 100), "%")),
position = position_stack(vjust = 0.5)) +
labs(title = "Tỷ lệ các dòng sản phẩm được sử dụng", fill = "Dòng sản phẩm") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5))
Nhận xét:
Biến ProductFamily phản ánh sự phân bổ sản phẩm theo nhóm. Trong tổng số 14,059 quan sát, nhóm Food chiếm phần lớn với 10,153 sản phẩm, tương ứng 72.2%. Nhóm Non-Consumable chiếm 2,656 sản phẩm, khoảng 18.9%, và nhóm Drink chiếm 1,250 sản phẩm, tương đương 8.9%. Điều này cho thấy khách hàng chủ yếu mua các sản phẩm thuộc nhóm thực phẩm, trong khi các nhóm đồ uống và hàng không tiêu thụ chiếm tỷ lệ nhỏ hơn.
1. Thống kê tần suất
# Lập bảng tần số
de1 <- table(d$ProductDepartment)
de1
##
## Alcoholic Beverages Baked Goods Baking Goods Beverages
## 356 425 1072 680
## Breakfast Foods Canned Foods Canned Products Carousel
## 188 977 109 59
## Checkout Dairy Deli Eggs
## 82 903 699 198
## Frozen Foods Health and Hygiene Household Meat
## 1382 893 1420 89
## Periodicals Produce Seafood Snack Foods
## 202 1994 102 1600
## Snacks Starchy Foods
## 352 277
Vậy trong bộ dữ liệu này có 356 là Alcoholic Beverages.
425 là Baked Goods.
1072 là Baking Goods.
680 là Beverages.
188 là Breakfast Foods.
977 là Canned Foods.
109 là Canned Products.
59 là Carousel.
82 là Checkout.
903 là Dairy.
699 là Deli.
198 là Eggs.
1382 là Frozen Foods.
893 là Health and Hygiene.
1420 là Household.
89 là Meat.
202 là Periodicals.
1994 là Produce.
102 là Seafood.
1600 là Snack Foods.
352 là Snacks.
277 là Starchy Foods.
# Lập bảng tần suất
de2 <- table(d$ProductDepartment)/sum(nrow(d))
de2
##
## 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
2.5321858 % là Alcoholic Beverages.
3.0229746 % là Baked Goods.
7.6250089 % là Baking Goods.
4.8367594 % là Beverages.
1.3372217 % là Breakfast Foods.
6.9492852 % là Canned Foods.
0.7753041 % là Canned Products.
0.41966 % là Carousel.
0.5832563 % là Checkout.
6.4229319 % là Dairy.
4.9719041 % là Deli.
1.4083505 % là Eggs.
9.8300021 % là Frozen Foods.
6.3518031 % là Health and Hygiene.
10.1002916 % là Household.
0.6330464 % là Meat.
1.436802 % là Periodicals.
14.1830856 % là Produce.
0.7255139 % là Seafood.
11.3806103 % là Snack Foods.
2.5037343 % là Snacks.
1.9702682 % là Starchy Foods.
3. Trực quan hóa
ggplot(as.data.frame(de1), aes(x = Freq, y = reorder(Var1, Freq))) +
geom_col(fill = "steelblue") +
geom_text(aes(label = paste0(Freq, " (", round(de2[Var1] * 100, 1), "%)")),
hjust = -0.1, color = "black") +
labs(title = "Số lượng các danh mục sản phẩm được sử dụng",
x = "Số lượng", y = "Danh mục sản phẩm") +
theme_minimal() +
xlim(0, max(as.data.frame(de1)$Freq) * 1.2)
Nhận xét:
Biến ProductDepartment thể hiện sự phân bố các sản phẩm theo từng phòng ban hay nhóm sản phẩm cụ thể. Trong tổng số 14,059 quan sát, các nhóm lớn nhất gồm:
Produce (Rau củ quả) với 1,994 sản phẩm, chiếm khoảng 14.18%,
Frozen Foods (Thực phẩm đông lạnh) với 1,382 sản phẩm, chiếm 9.83%,
Household (Đồ gia dụng) với 1,420 sản phẩm, chiếm 10.1%,
Snack Foods (Đồ ăn nhẹ) với 1,600 sản phẩm, chiếm 11.38%,
Baking Goods (Nguyên liệu làm bánh) với 1,072 sản phẩm, chiếm 7.63%.
Các nhóm khác như Dairy (Sữa), Health and Hygiene (Sức khỏe và vệ sinh), Beverages (Đồ uống) cũng chiếm tỷ lệ tương đối lớn từ 4% đến 6%. Một số nhóm nhỏ hơn như Carousel, Checkout, Seafood chiếm phần nhỏ dưới 1%. Điều này cho thấy khách hàng mua đa dạng sản phẩm, nhưng tập trung chủ yếu vào nhóm thực phẩm tươi, đông lạnh, đồ ăn nhẹ và các vật dụng gia đình.
1. Thống kê Tần suất
ca1 <- table(d$ProductCategory)
ca1
##
## Baking Goods Bathroom Products Beer and Wine
## 484 365 356
## Bread Breakfast Foods Candles
## 425 417 45
## Candy Canned Anchovies Canned Clams
## 352 44 53
## Canned Oysters Canned Sardines Canned Shrimp
## 35 40 38
## Canned Soup Canned Tuna Carbonated Beverages
## 404 87 154
## Cleaning Supplies Cold Remedies Dairy
## 189 93 903
## Decongestants Drinks Eggs
## 85 135 198
## Electrical Frozen Desserts Frozen Entrees
## 355 323 118
## Fruit Hardware Hot Beverages
## 765 129 226
## Hygiene Jams and Jellies Kitchen Products
## 197 588 217
## Magazines Meat Miscellaneous
## 202 761 42
## Packaged Vegetables Pain Relievers Paper Products
## 48 192 345
## Pizza Plastic Products Pure Juice Beverages
## 194 141 165
## Seafood Side Dishes Snack Foods
## 102 153 1600
## Specialty Starchy Foods Vegetables
## 289 277 1728
Vậy trong bộ dữ liệu này có:
484 là Baking Goods.
365 là Bathroom Products.
356 là Beer and Wine.
425 là Bread.
417 là Breakfast Foods.
45 là Candles.
352 là Candy.
44 là Canned Anchovies.
53 là Canned Clams.
35 là Canned Oysters.
40 là Canned Sardines.
38 là Canned Shrimp.
404 là Canned Soup.
87 là Canned Tuna.
154 là Carbonated Beverages.
189 là Cleaning Supplies.
93 là Cold Remedies.
903 là Dairy.
85 là Decongestants.
135 là Drinks.
198 là Eggs.
355 là Electrical.
323 là Frozen Desserts.
118 là Frozen Entrees.
765 là Fruit.
129 là Hardware.
226 là Hot Beverages.
197 là Hygiene.
588 là Jams and Jellies.
217 là Kitchen Products.
202 là Magazines.
761 là Meat.
42 là Miscellaneous.
48 là Packaged Vegetables.
192 là Pain Relievers.
345 là Paper Products.
194 là Pizza.
141 là Plastic Products.
165 là Pure Juice Beverages.
102 là Seafood.
153 là Side Dishes.
1600 là Snack Foods.
289 là Specialty.
277 là Starchy Foods .
1728 là Vegetables.
# Lập bảng tần suất
ca2 <- table(d$ProductCategory)/sum(nrow(d))
ca2
##
## 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
Vậy trong bộ dữ liệu này có:
1.9702682 % là Starchy Foods.
3.4426346 % là Baking Goods.
2.5962017 % là Bathroom Products.
2.5321858 % là Beer and Wine.
3.0229746 % là Bread.
2.9660716 % là Breakfast Foods.
0.3200797 % là Candles.
2.5037343 % là Candy.
0.3129668 % là Canned Anchovies.
0.3769827 % là Canned Clams.
0.2489508 % là Canned Oysters.
0.2845153 % là Canned Sardines.
0.2702895 % là Canned Shrimp.
2.8736041 % là Canned Soup.
0.6188207 % là Canned Tuna.
1.0953837 % là Carbonated Beverages.
1.3443346 % là Cleaning Supplies.
0.661498 % là Cold Remedies.
6.4229319 % là Dairy.
0.6045949 % là Decongestants.
0.960239 % là Drinks.
1.4083505 % là Eggs.
2.5250729 % là Electrical.
2.2974607 % là Frozen Desserts.
0.83932 % là Frozen Entrees.
5.4413543 % là Fruit.
0.9175617 % là Hardware.
1.6075112 % là Hot Beverages.
1.4012376 % là Hygiene.
4.1823743 % là Jams and Jellies.
1.5434953 % là Kitchen Products.
1.436802 % là Magazines.
5.4129028 % là Meat.
0.298741 % là Miscellaneous.
0.3414183 % là Packaged Vegetables.
1.3656732 % là Pain Relievers.
2.4539441 % là Paper Products.
1.379899 % là Pizza.
1.0029163 % là Plastic Products.
1.1736254 % là Pure Juice Beverages.
0.7255139 % là Seafood.
1.0882709 % là Side Dishes.
11.3806103 % là Snack Foods.
2.0556227 % là Specialty.
1.9702682 % là Starchy Foods .
12.2910591 % là Vegetables.
ggplot(as.data.frame(ca1), aes(x = Freq, y = reorder(Var1, Freq))) +
geom_col(fill = "steelblue") +
geom_text(aes(label = paste0(Freq, " (", round(as.data.frame(ca2)$Freq, 4), "%)")),
hjust = -0.1, size = 3) +
scale_x_continuous(expand = expansion(mult = c(0, 0.3))) +
labs(
title = "Biểu đồ sự phân bố của các danh mục sản phẩm được sử dụng",
x = "Số lượng",
y = "Danh mục sản phẩm"
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5, size = 14),
axis.text.y = element_text(size = 8)
)
Nhận xét:
Biến ProductCategory mô tả sự phân bố của các danh mục sản phẩm được khách hàng lựa chọn. Các nhóm chiếm tỷ lệ lớn gồm:
Vegetables (Rau củ): 1,728 sản phẩm, chiếm khoảng 12.29% tổng số,
Snack Foods (Đồ ăn nhẹ): 1,600 sản phẩm, chiếm 11.38%,
Meat (Thịt): 761 sản phẩm, chiếm 5.41%,
Dairy (Sữa): 903 sản phẩm, chiếm 6.42%,
Baking Goods (Nguyên liệu làm bánh): 484 sản phẩm, chiếm 3.44%,
Bread (Bánh mì): 425 sản phẩm, chiếm 3.02%,
Fruit (Trái cây): 765 sản phẩm, chiếm 5.44%,
Frozen Foods chia thành nhiều nhóm nhỏ như Frozen Desserts (Kem đông lạnh) 323 sản phẩm (2.3%), Frozen Entrees (Món đông lạnh) 118 sản phẩm (0.8%).
Các danh mục nhỏ hơn như Beer and Wine (Rượu bia), Candles (Nến), Canned Seafood (Hải sản đóng hộp), Cleaning Supplies (Dụng cụ vệ sinh) cũng góp mặt với tỷ lệ nhỏ từ khoảng 0.2% đến 3%.
Nhận xét:
Khách hàng chủ yếu tập trung mua các nhóm sản phẩm tươi sống, đồ ăn nhẹ, các sản phẩm từ sữa và thực phẩm chế biến sẵn phục vụ cho nhu cầu ăn uống hàng ngày. Các sản phẩm đa dạng từ đồ uống, gia dụng đến các sản phẩm phụ trợ khác cũng có sự hiện diện, cho thấy bộ dữ liệu rất phong phú và đa dạng.
3 hạng mục được chọn bào gồm:
Hạng mục “F” của biến “Gender”.
Hạng mục “Y” của biến “Homeowner”.
Hạng mục “S” của biến “MaritalStatus”.
prop.test(sum(data$Gender == "F"), nrow(d), conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: sum(data$Gender == "F") out of nrow(d), null probability 0.5
## X-squared = 5.5765, df = 1, p-value = 0.0182
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5016931 0.5182886
## sample estimates:
## p
## 0.5099936
Giả thuyết kiểm định:
H₀ (Giả thuyết không): Tỷ lệ khách hàng là nữ = 0.5
H₁ (Giả thuyết đối): Tỷ lệ khách hàng là nữ ≠ 0.5
Vì p-value = 0.0182 < 0.05, ta bác bỏ giả thuyết không (H₀).Như vậy, có bằng chứng thống kê cho thấy tỷ lệ khách hàng nữ khác 50% trong dân số.
Nhận xét: Dựa trên mẫu khảo sát, khoảng 51% khách hàng là nữ. Kết quả kiểm định cho thấy tỷ lệ này khác một cách có ý nghĩa thống kê so với giả thuyết 50%.
Khoảng tin cậy 95% cho thấy tỷ lệ khách hàng nữ trong tổng thể có thể nằm trong khoảng [50.17% ; 51.83%], và vì khoảng này không chứa giá trị 0.5, điều đó củng cố việc bác bỏ H₀.
prop.test(sum(data$Homeowner == "Y"), nrow(d), conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: sum(data$Homeowner == "Y") out of nrow(d), null probability 0.5
## X-squared = 568.86, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5924537 0.6087145
## sample estimates:
## p
## 0.6006117
Giả thuyết kiểm định:
H₀ (Giả thuyết không): Tỷ lệ khách hàng là chủ nhà = 0.5
H₁ (Giả thuyết đối): Tỷ lệ khách hàng là chủ nhà ≠ 0.5
Vì p-value < 0.05, ta bác bỏ giả thuyết không (H₀). Như vậy, có bằng chứng thống kê cho thấy tỷ lệ khách hàng là chủ nhà KHÁC 50%.
Nhận xét: Trong mẫu khảo sát, khoảng 60.06% khách hàng là chủ nhà, và khoảng tin cậy 95% cho thấy tỷ lệ này trong tổng thể có thể nằm trong khoảng [59.25% ; 60.87%].
prop.test(sum(data$MaritalStatus == "S"),nrow(d), conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: sum(data$MaritalStatus == "S") out of nrow(d), null probability 0.5
## X-squared = 7.5593, df = 1, p-value = 0.00597
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5033292 0.5199235
## sample estimates:
## p
## 0.5116296
Giả thuyết kiểm định:
H₀ (Giả thuyết không): Tỷ lệ khách hàng độc thân = 0.5
H₁ (Giả thuyết đối): Tỷ lệ khách hàng độc thân ≠ 0.5
Vì p-value = 0.0058 < 0.05, ta bác bỏ giả thuyết không (H₀).Tức là, có bằng chứng thống kê cho thấy tỷ lệ khách hàng độc thân khác 50%.
Nhận xét:Trong mẫu khảo sát, khoảng 51.16% khách hàng là độc thân. Khoảng tin cậy 95% cho thấy tỷ lệ này trong dân số có thể nằm trong khoảng [50.34% ; 51.99%].
# bảng tần suất chéo
ge_ma1 <-table(d$Gender, d$MaritalStatus)
ge_ma1
##
## M S
## F 3602 3568
## M 3264 3625
Phân bố tình trạng hôn nhân theo giới tính:
Có 3602 người đã kết hôn.
Có 3602 người độc thân.
Có 3264 người đã kết hôn.
Có 3264 người độc thân.
➡ Nữ có nhiều người đã kết hôn hơn nam, trong khi nam có nhiều người độc thân hơn nữ.
# Tính tỷ lệ phần trăm theo hàng
ge_ma2 <- prop.table(ge_ma1, margin = 1) * 100
ge_ma2
##
## M S
## F 50.23710 49.76290
## M 47.37988 52.62012
Phân tích theo hàng cho thấy sự khác biệt nhẹ trong tình trạng hôn nhân giữa hai giới:
Trong nhóm nữ, tỷ lệ đã kết hôn chiếm 50.237099 % nhỉnh hơn tỷ lệ độc thân chiếm 50.237099 %, cho thấy nữ có xu hướng kết hôn nhiều hơn.
Trong nhóm nam, tỷ lệ độc thân chiếm47.379881 % cao hơn tỷ lệ đã kết hôn chiếm 47.379881 %, cho thấy nam có xu hướng độc thân cao hơn nữ.
ggplot(as.data.frame(ge_ma1), aes(x = Var1, y = Freq, fill = Var2)) +
geom_col(position = position_dodge(width = 0.9)) +
geom_text(aes(label = paste0(Freq, " (", round(ge_ma2[cbind(as.character(Var1), as.character(Var2))], 1), "%)")),
position = position_dodge(width = 0.9),
vjust = -0.3, size = 3) +
labs(title = "Giới tính và Tình trạng hôn nhân",
x = "Giới tính",
y = "Số lượng",
fill = "Tình trạng hôn nhân") +
theme_minimal()
Nhận xét:
Nữ giới có xu hướng kết hôn cao hơn một chút so với độc thân (50.24% vs 49.76%).Nam giới lại có tỷ lệ độc thân nhỉnh hơn kết hôn (52.62% vs 47.38%).Sự khác biệt giữa hai giới trong tình trạng hôn nhân là không quá lớn, cho thấy một sự phân bố tương đối cân bằng giữa nam và nữ trong cả hai nhóm hôn nhân.
Việc phân tích cặp biến như vậy giúp hiểu rõ hơn về mối quan hệ giữa giới tính và tình trạng hôn nhân, và có thể là gợi ý quan trọng trong các nghiên cứu liên quan đến hành vi tiêu dùng, xã hội học hoặc phân khúc thị trường.
Giả thuyết:
H0: Gender và MaritalStatus độc lập nhau (không có mối liên hệ).
H1: Gender và MaritalStatus có liên quan với nhau (phụ thuộc nhau).
# kiểm định Chi-bình phương
chi1 <- chisq.test(ge_ma1)
chi1
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: ge_ma1
## X-squared = 11.365, df = 1, p-value = 0.0007485
Kết quả cung cấp:
Giá trị Chi-bình phương (X²): 11.365
Bậc tự do (df): 1
Giá trị p: p = 0.0007485
Ta có p = 0.0007485 < 0.05 → bác bỏ giả thuyết H0 ở mức ý nghĩa α = 0.05. Vậy nên có mối quan hệ có ý nghĩa thống kê giữa Giới tính và Tình trạng hôn nhân.
kết luận thêm: Kết quả kiểm định Chi-bình phương (X² = 11.365, df = 1, p = 0.0007485) cho thấy có mối quan hệ có ý nghĩa thống kê giữa giới tính và tình trạng hôn nhân ở mức ý nghĩa α = 0.05. Điều này cho thấy giới tính có liên quan đến tình trạng hôn nhân trong dữ liệu. Cụ thể, nữ giới có xu hướng kết hôn nhiều hơn, trong khi nam giới có tỷ lệ độc thân cao hơn. Mặc dù sự khác biệt về tỷ lệ là nhỏ, nhưng với kích thước mẫu lớn, mối liên hệ này là có ý nghĩa thống kê.
# bảng tần suất chéo
fa_co1 <-table(d$Country, d$ProductFamily)
fa_co1
##
## Drink Food Non-Consumable
## Canada 69 580 160
## Mexico 325 2683 680
## USA 856 6890 1816
Phân bố hàng hóa trong các quốc gia:
Với đồ uống: 856; Thực phẩm: 6,890; Thực phẩm không tiêu dùng trực tiếp: 1,816
Với đồ uống: 325; Thực phẩm: 2,683; Thực phẩm không tiêu dùng trực tiếp: 680
Với đồ uống:69; Thực phẩm: 580; Thực phẩm không tiêu dùng trực tiếp: 160
Canada: 580; Mexico: 2,683; USA: 6,890
# Tính tỷ lệ phần trăm theo hàng
fa_co2 <- prop.table(fa_co1, margin = 1) * 100
fa_co2
##
## Drink Food Non-Consumable
## Canada 8.529048 71.693449 19.777503
## Mexico 8.812364 72.749458 18.438178
## USA 8.952102 72.056055 18.991843
Tại Canada sản phẩm đồ uống chiếm 8.5290482 %, thực phẩm chiếm 8.5290482 %, thực phẩm không tiêu dùng chiếm 8.5290482 %.
Tại Mexico sản phẩm đồ uống chiếm 8.8123644 %, thực phẩm chiếm 8.8123644 %, thực phẩm không tiêu dùng chiếm 8.8123644 %.
Tại USA sản phẩm đồ uống chiếm 8.9521021 %, thực phẩm chiếm 8.9521021 %, thực phẩm không tiêu dùng chiếm 8.9521021 %.
ggplot(as.data.frame(fa_co1), aes(x = Var1, y = Freq, fill = Var2)) +
geom_col(position = position_dodge(width = 0.9)) +
geom_text(aes(label = paste0(Freq, " (", round(fa_co2[cbind(as.character(Var1), as.character(Var2))], 1), "%)")),
position = position_dodge(width = 0.9),
vjust = -0.3, size = 3) +
labs(title = "Phân bố Sản phẩm theo Quốc gia",
x = "Dòng sản phẩm",
y = "Số lượng",
fill = "Quốc gia") +
theme_minimal()
Nhận xét:
cơ cấu phân phối sản phẩm giữa các quốc gia có tính nhất quán cao. Cụ thể, nhóm hàng Food chiếm tỷ trọng lớn nhất trong cả ba quốc gia, dao động từ khoảng 71% đến 73%. Nhóm Non-Consumable chiếm khoảng 18–20%, trong khi nhóm Drink chỉ chiếm xấp xỉ 8–9%. Điều này phản ánh sự tương đồng trong xu hướng tiêu dùng và phân phối hàng hóa giữa các nước thuộc khu vực Bắc Mỹ, có thể do đặc điểm văn hóa, nhu cầu tiêu dùng hoặc chiến lược phân phối đồng nhất của doanh nghiệp.
Tuy nhiên, xét về số lượng tuyệt đối, sự khác biệt giữa các quốc gia là khá rõ rệt. Hoa Kỳ có tổng số lượng sản phẩm thuộc cả ba nhóm cao nhất, tiếp đến là Mexico và cuối cùng là Canada. Ví dụ, Hoa Kỳ có tới 6890 sản phẩm thuộc nhóm Food, trong khi con số này ở Canada chỉ là 580. Mặc dù cơ cấu phân phối tương tự nhau, quy mô thị trường tại Hoa Kỳ lớn hơn nhiều lần so với Canada và Mexico, phản ánh sức mua và độ phủ thị trường cao hơn.
Tóm lại, dữ liệu cho thấy các quốc gia có cấu trúc phân phối sản phẩm tương đồng, nhưng khác biệt về quy mô thị trường, đây là yếu tố quan trọng cần xem xét trong chiến lược kinh doanh và tiếp thị theo từng khu vực.
Giả thuyết
H0: ProductFamily và Country độc lập nhau (không có mối liên hệ).
H1: ProductFamily và Country có liên quan với nhau (phụ thuộc nhau).
# kiểm định Chi-bình phương
chi2 <- chisq.test(fa_co1)
chi2
##
## Pearson's Chi-squared test
##
## data: fa_co1
## X-squared = 1.1831, df = 4, p-value = 0.8809
Kết quả cung cấp:
Giá trị Chi-bình phương (X²): 1.1831
Bậc tự do (df): 4
Giá trị p: p = 0.8809
Ta có p = 0.8809 > 0.05 → chấp nhận giả thuyết H0 ở mức ý nghĩa α = 0.05. Vậy nên không tồn tại mối quan hệ có ý nghĩa thống kê giữa Phân bố sản phẩm và Quốc gia.
# bảng tần suất chéo
an_ho1 <-table(d$AnnualIncome, d$Homeowner)
an_ho1
##
## N Y
## $10K - $30K 1359 1731
## $110K - $130K 119 524
## $130K - $150K 136 624
## $150K + 48 225
## $30K - $50K 2087 2514
## $50K - $70K 1063 1307
## $70K - $90K 686 1023
## $90K - $110K 117 496
# Tính tỷ lệ phần trăm theo hàng
an_ho2 <- prop.table(an_ho1, margin = 1) * 100
an_ho2
##
## N Y
## $10K - $30K 43.98058 56.01942
## $110K - $130K 18.50700 81.49300
## $130K - $150K 17.89474 82.10526
## $150K + 17.58242 82.41758
## $30K - $50K 45.35970 54.64030
## $50K - $70K 44.85232 55.14768
## $70K - $90K 40.14043 59.85957
## $90K - $110K 19.08646 80.91354
ggplot(as.data.frame(an_ho1), aes(x = Var1, y = Freq, fill = Var2)) +
geom_col(position = position_dodge(width = 0.9)) +
geom_text(aes(label = paste0(Freq, " (", round(an_ho2[cbind(as.character(Var1), as.character(Var2))], 1), "%)")),
position = position_dodge(width = 0.9),
vjust = -0.3, size = 3) +
labs(title = "Thu nhập và Tình trạng sở hữu nhà",
x = "Thu nhập hàng năm",
y = "Số lượng",
fill = "Sở hữu nhà") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Nhận xét:
Ở các mức thu nhập thấp hơn, ví dụ nhóm $10K - $30K và $30K - $50K, tỷ lệ sở hữu nhà (Y) dao động quanh mức 54% đến 56%. Điều này cho thấy dù thu nhập thấp, vẫn có một tỷ lệ đáng kể người trong nhóm này là chủ nhà.
Tuy nhiên, khi thu nhập tăng lên các nhóm cao hơn, đặc biệt từ $110K trở lên, tỷ lệ sở hữu nhà tăng rất mạnh, vượt trên 80%. Cụ thể, nhóm thu nhập $110K - $130K có tới 81.5% chủ nhà, và các nhóm $130K - $150K và $150K+ tỷ lệ này tiếp tục duy trì trên 82%. Đây là chỉ báo rõ ràng cho thấy thu nhập càng cao thì khả năng và tỷ lệ sở hữu nhà càng lớn.
Ngoài ra, các nhóm thu nhập trung bình như $50K - $70K, $70K - $90K, và $90K - $110K có tỷ lệ sở hữu nhà từ khoảng 55% đến gần 81%, thể hiện xu hướng tăng dần với mức thu nhập.
Tổng kết lại, dữ liệu cho thấy một mối tương quan tích cực giữa mức thu nhập và quyền sở hữu nhà, phản ánh thực tế kinh tế phổ biến: thu nhập cao tạo điều kiện thuận lợi hơn để mua và sở hữu nhà ở.
Giả thuyết:
H0: AnnualIncome và Homeowner độc lập nhau (không có mối liên hệ).
H1: AnnualIncome và Homeowner có liên quan với nhau (phụ thuộc nhau).
# kiểm định Chi-bình phương
chi3 <- chisq.test(an_ho1)
chi3
##
## Pearson's Chi-squared test
##
## data: an_ho1
## X-squared = 546.37, df = 7, p-value < 2.2e-16
Kết quả cung cấp:
Giá trị Chi-bình phương (X²): 546.37
Bậc tự do (df): 7
Giá trị p: p < 2.2e-16
Ta có p < 0.05 → bác bỏ giả thuyết H0 ở mức ý nghĩa α = 0.05. Vậy nên có mối quan hệ có ý nghĩa thống kê giữa Mức thu nhập và Tình trạng sở hữu nhà.
kết luận thêm: Kết quả kiểm định Chi-bình phương (X² = 546.37, df = 7, p < 2.2e-16) cho thấy có mối quan hệ có ý nghĩa thống kê giữa Mức thu nhập và Tình trạng sở hữu nhà ở mức ý nghĩa α = 0.05. Điều này cho thấy mức thu nhập có liên quan đến tình trạng sở hữu nhà trong dữ liệu. Có thể quan sát rằng, ở mọi mức thu nhập, số lượng người sở hữu nhà (Y) luôn vượt trội hơn số người không sở hữu nhà (N). Đặc biệt, khi mức thu nhập tăng cao, sự chênh lệch này càng rõ rệt, với số người sở hữu nhà tăng mạnh so với không sở hữu.Điều này phản ánh xu hướng hợp lý trong thực tế: thu nhập càng cao, khả năng và tỷ lệ sở hữu nhà càng lớn.
Dựa trên tất cả các phân tích trên, Những hiểu biết quan trọng nhất về đặc điểm khách hàng và hành vi mua sắm của họ từ các biến định tính được kết luận như sau:
-> Khách hàng nữ có xu hướng đã kết hôn nhiều hơn, trong khi nam giới nhiều người còn độc thân – cho thấy các giai đoạn khác nhau trong vòng đời cá nhân có thể gắn liền với các hành vi tiêu dùng khác nhau.
-> Khách hàng ở các quốc gia khác nhau có đặc điểm tiêu dùng khác nhau, tuy cùng ưu tiên thực phẩm nhưng thị trường Mỹ cho thấy sự đa dạng hơn trong nhu cầu – tiềm năng cho các dòng sản phẩm ngoài thực phẩm.
-> Thu nhập càng cao thì khả năng sở hữu nhà càng lớn, phản ánh một xu hướng tiêu dùng dài hạn và ổn định hơn ở nhóm khách hàng có năng lực tài chính.
Phân tích chỉ giới hạn ở biến định tính: Phân tích hiện tại chủ yếu tập trung vào các biến định tính như Gender, MaritalStatus, Homeowner, AnnualIncome, Country, và ProductFamily, trong khi các biến định lượng quan trọng như Revenue, UnitsSold, hoặc số lượng Children chưa được phân tích sâu. Do đó, những phát hiện hiện tại mới chỉ mô tả đặc điểm phân loại của khách hàng, chưa phản ánh được giá trị kinh tế hay mức độ tiêu dùng thực tế.
Một số nhóm con có kích thước mẫu nhỏ: Một số nhóm trong các biến phân loại như AnnualIncome (ví dụ: “$150K +”), Country (ví dụ: “Canada”) hoặc ProductFamily (ví dụ: “Drink”) có số lượng quan sát rất nhỏ so với các nhóm khác. Điều này có thể làm sai lệch kết quả kiểm định thống kê hoặc gây nhiễu trong việc suy diễn tổng thể.
Chưa phân tích mối quan hệ nhiều chiều giữa các biến: Các phân tích hiện tại chủ yếu xem xét từng cặp biến riêng lẻ (bivariate), mà chưa khai thác mối quan hệ đồng thời giữa nhiều biến (multivariate). Điều này hạn chế khả năng phát hiện các tương tác phức tạp giữa các yếu tố khách hàng (ví dụ: giới tính, thu nhập và quốc gia) ảnh hưởng đến hành vi mua hàng.
Hiện tại, phân tích chủ yếu tập trung vào các biến định tính mà chưa khai thác đầy đủ các biến định lượng như doanh thu, số lượng sản phẩm bán ra hay số con trong gia đình. Việc bổ sung phân tích các biến định lượng sẽ giúp doanh nghiệp hiểu rõ hơn về giá trị thực tế và hành vi tiêu dùng của khách hàng, từ đó đưa ra các chiến lược marketing và chăm sóc khách hàng hiệu quả hơn.
Một số nhóm trong các biến phân loại có kích thước mẫu rất nhỏ, làm giảm tính đại diện và có thể dẫn đến sai lệch trong kết quả phân tích. Doanh nghiệp nên xem xét gộp các nhóm nhỏ tương tự hoặc tăng cường thu thập dữ liệu để đảm bảo mẫu nghiên cứu đủ lớn, giúp kết quả phân tích chính xác và đáng tin cậy hơn.
Các phân tích hiện tại chỉ xem xét mối quan hệ đơn giản giữa từng cặp biến, chưa khai thác được các tương tác phức tạp giữa nhiều yếu tố cùng lúc. Áp dụng các phương pháp phân tích đa biến sẽ giúp phát hiện những nhóm khách hàng tiềm năng với đặc điểm đa chiều, từ đó xây dựng chiến lược phân loại sản phẩm, nhắm mục tiêu và cá nhân hóa chiến dịch marketing phù hợp, nâng cao hiệu quả kinh doanh.
Liệu có thể xây dựng được mô hình dự báo chính xác hơn về khả năng mua hàng hoặc giá trị vòng đời khách hàng (Customer Lifetime Value) dựa trên dữ liệu đa chiều kết hợp định tính và định lượng không?
Tác động của yếu tố văn hóa, địa lý hoặc mùa vụ đến thói quen mua sắm và lựa chọn sản phẩm của khách hàng có thể được mô hình hóa như thế nào?
Mối quan hệ giữa các biến định tính và định lượng có sự thay đổi theo thời gian hay theo các sự kiện đặc biệt (ví dụ: mùa lễ hội, khuyến mãi) không? Nếu có, doanh nghiệp cần điều chỉnh chiến lược như thế nào?
Phương pháp phân tích đa chiều nào (ví dụ: phân tích nhân tố, phân tích cụm, hồi quy logistic đa biến) phù hợp nhất để mô hình hóa hành vi phức tạp của khách hàng trong dữ liệu này?
data <- read.csv("C:/Users/Ngo Trang/Documents/Supermarket Transactions.csv", header = TRUE)
str(data)
## '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 ...
Bảng tần số chéo (hay còn gọi là bảng chéo, bảng tần số kết hợp, contingency table, hoặc cross-tabulation) là một công cụ thống kê được sử dụng để mô tả mối quan hệ giữa hai (hoặc nhiều) biến phân loại (categorical variables).
Ví dụ:
vd1 <- table(data$MaritalStatus, data$Homeowner)
vd1
##
## N Y
## M 1719 5147
## S 3896 3297
Trong bộ dữ liệu bao gồm 1719 người đã kết hôn và không sở hữu nhà, 5147 người đã kết hôn và sở hữu nhà, 3896 người độc thân và không sở hưu nhà, 3297 người độc thân và sở hữu nhà.
vd2 <- table(data$MaritalStatus, data$ProductFamily)
vd2
##
## Drink Food Non-Consumable
## M 628 4938 1300
## S 622 5215 1356
Trong bộ dữ liệu bao gồm 628 người đã kết hôn sử dụng đồ uống, 4938 người đã kết hôn và sử dụng thực phẩm và 1300 người đã kết hôn sử dụng sản phẩm không sử dụng trực tiếp. bên cạnh đó bao gồm 622 người độc thân sử dụng đồ uống, 5215 người độc thân sử dụng thực phẩm và 1356 người sử dụng sản phẩm không dùng trực tiếp.
Kiểm định Chi-bình phương (Chi-square test) về tính độc lập là một phương pháp thống kê dùng để kiểm tra xem hai biến phân loại (categorical variables) có mối liên hệ với nhau hay không — hay nói cách khác, chúng có độc lập hay không.
Mục đích kiểm định:
Giả thuyết không (H₀): Hai biến phân loại độc lập với nhau (không có mối quan hệ).
Giả thuyết đối (H₁): Hai biến phân loại không độc lập (có mối quan hệ).
Ví dụ:
Giả thuyết:
H₀ : MaritalStatus và Homeowner độc lập với nhau (không có mối quan hệ).
H₁ : MaritalStatus và Homeowneri không độc lập (có mối quan hệ).
chisq.test(vd1)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: vd1
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
Qua kết quả kiểm định cho ta p−value < 2e−16 < 0.05, nên bác bỏ H0, nghĩa là giữa việc sở hữu nhà và tình trạng hôn nhân là có liên quan với nhau.
Giả thuyết:
H₀ : MaritalStatus và ProductFamily độc lập với nhau (không có mối quan hệ).
H₁ : MaritalStatus và ProductFamily không độc lập (có mối quan hệ).
chisq.test(vd2)
##
## Pearson's Chi-squared test
##
## data: vd2
## X-squared = 1.1617, df = 2, p-value = 0.5594
Qua kết quả kiểm định cho ta p−value = 0.5594 > 0.05, không đủ cơ sở bác bỏ H0, nghĩa là giữa việc sở hữu nhà và tình trạng hôn nhân độc lập với nhau.
(Relative risk) - Rủi ro tương đối giữa 2 biểu hiện khác nhau của biến phụ thuộc. Relative Risk (RR) là một chỉ số thống kê dùng để so sánh xác suất xảy ra một sự kiện giữa hai nhóm.
Ký hiệu πi là tỷ lệ “thành công” của biến phụ thuộc (response variable) tương ứng với từng biểu hiện của biến độc lập.
Từ bảng tần xuất, chúng ta tính π1/π2, phân số này gọi là Rủi ro tương đối (Relative risk) giữa 2 biểu hiện khác nhau của biến phụ thuộc.
Ví dụ:
addmargins(vd1) # Bảng phân phối xác suất biên
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
Chúng ta tính rủi ro tương đối (relative risk).
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.3.3
RelRisk(vd1)
## [1] 0.4622354
Xác suất làm chủ nhà ở nhóm M (Kết hôn):
P(Y/M) = 5147/6866 = 0.75
Xác suất làm chủ nhà ở nhóm S (Độc thân):
P(Y/S) = 3297/7193 = 0.4583
Công thức tính Relative Risk
RR = P(Y/S)/ P(Y/M) = 0.4583/0.75 ≈ 0.4622
Ý nghĩa kết quả RR = 0.4622
RR < 1: Nhóm S (Độc thân) có xác suất làm chủ nhà thấp hơn nhóm M (Kết hôn).
Cụ thể, người độc thân có khả năng làm chủ nhà bằng khoảng 46% so với người kết hôn. Hay nói cách khác, người kết hôn có khả năng làm chủ nhà cao hơn người độc thân khoảng 1/0.4622 ≈ 2.16 lần.
Lệnh RelRisk(tmp) trong R
Hàm RelRisk() từ package DescTools dùng để tính rủi ro tương đối từ bảng tần suất chéo.Mặc định, nó lấy tỷ lệ tại vị trí hàng 2 (S) so với hàng 1 (M) cho cột 2 (Y) so với cột 1 (N). Nên kết quả 0.4622 đúng là rủi ro tương đối cho nhóm S so với nhóm M về việc làm chủ nhà.
Bảng ngẫu nhiên (Contingency Table)
Bảng ngẫu nhiên là bảng tần số thể hiện số lần xuất hiện của các kết hợp giữa hai (hoặc nhiều) biến phân loại. Dạng phổ biến nhất là bảng 2 chiều, ví dụ:
vd1 <- table(data$MaritalStatus, data$Homeowner)
addmargins(vd1)
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
Phân phối Poisson và Multinomial là hai phân phối thường dùng để sinh ra bảng ngẫu nhiên vì đặc điểm cấu trúc xác suất của chúng. Với phân phối Poisson, mỗi ô trong bảng được coi là một biến ngẫu nhiên đếm độc lập, không ràng buộc bởi tổng dòng hay cột, nên toàn bộ bảng có thể thay đổi tự do – tạo nên tính ngẫu nhiên của bảng. Ngược lại, phân phối Multinomial sinh ra bảng ngẫu nhiên trong trường hợp tổng số đếm được cố định trước, nhưng các phần tử được phân phối ngẫu nhiên vào các ô dựa trên xác suất, từ đó tạo ra nhiều khả năng cấu hình bảng khác nhau. Do đó, cả hai phân phối này đều là mô hình xác suất hợp lý để sinh bảng ngẫu nhiên trong các tình huống khác nhau.
Phân phối Poisson
Phân phối Poisson là một phân phối xác suất rời rạc dùng để mô tả số lần xảy ra của một sự kiện hiếm gặp trong một khoảng thời gian hoặc không gian cố định, với giả định rằng các sự kiện xảy ra độc lập và với tốc độ trung bình không đổi. Phân phối này được ký hiệu là:
\[ Y \sim \text{Poisson}(\lambda) \]
Trong đó:
Hàm xác suất của phân phối Poisson được viết như sau:
\[ P(Y = y) = \frac{e^{-\lambda} \lambda^y}{y!}, \quad y = 0, 1, 2, \dots \]
Phân phối Poisson thường được sử dụng để mô hình hóa dữ liệu đếm như số ca bệnh, số cuộc gọi, số lỗi kỹ thuật,… và là một thành phần cơ bản trong các mô hình tuyến tính tổng quát (GLM) khi biến phản hồi là dạng đếm.
Multinomial
Phân phối Multinomial là một mở rộng của phân phối nhị thức (Bernoulli) cho nhiều hơn hai kết quả. Phân phối này mô tả xác suất của các kết quả đếm được trong \(n\) lần thử, trong đó mỗi lần thử có thể rơi vào một trong \(k\) loại (categories) với xác suất tương ứng. Phân phối này được ký hiệu là:
\[ \mathbf{Y} \sim \text{Multinomial}(n, \mathbf{p}) \]
Trong đó:
Hàm xác suất:
\[ P(Y_1 = y_1, \dots, Y_k = y_k) = \frac{n!}{y_1! \cdots y_k!} p_1^{y_1} \cdots p_k^{y_k} \]
Phân phối Multinomial thường dùng để mô hình hóa các bảng tần suất hoặc bảng phân loại (contingency tables) khi tổng số đếm đã được cố định trước.
Xét một bảng tần suất ngẫu nhiên \(2 \times 2\) như sau:
| Biến A xảy ra | Biến A không xảy ra | Tổng | |
|---|---|---|---|
| Nhóm 1 | \(a\) | \(b\) | \(a + b\) |
| Nhóm 2 | \(c\) | \(d\) | \(c + d\) |
| Tổng | \(a + c\) | \(b + d\) | \(n\) |
Trong phân tích thống kê, ba chỉ số phổ biến để so sánh tỷ lệ giữa hai nhóm là:
1. Hiệu hai tỷ lệ (Risk Difference - RD)
Hiệu hai tỷ lệ đo lường sự chênh lệch tuyệt đối giữa xác suất xảy ra của biến A trong hai nhóm:
\[ \text{RD} = \frac{a}{a + b} - \frac{c}{c + d} \]
2. Tỷ số nguy cơ (Relative Risk - RR)
Tỷ số nguy cơ là tỷ lệ giữa xác suất xảy ra của biến A ở nhóm 1 so với nhóm 2:
\[ \text{RR} = \frac{a / (a + b)}{c / (c + d)} \]
3. Tỷ số chênh (Odds Ratio - OR)
Tỷ số chênh là tỷ lệ giữa odds (tỷ lệ chênh lệch giữa xảy ra và không xảy ra) của biến A ở hai nhóm:
\[ \text{OR} = \frac{a / b}{c / d} = \frac{a \cdot d}{b \cdot c} \]
Khi so sánh hai tỷ lệ trong bảng ngẫu nhiên \(2 \times 2\), các tham số phổ biến để đo mối liên hệ giữa hai biến phân loại gồm:
Để đánh giá độ chính xác của các tham số ước lượng này, ta thường tính khoảng tin cậy (Confidence Interval – CI) với mức tin cậy \((1 - \alpha)\), thường là 95%.
Khoảng tin cậy cho Odds Ratio
Odds Ratio (OR) được định nghĩa là:
\[ \hat{OR} = \frac{a \cdot d}{b \cdot c} \]
với \(a, b, c, d\) là tần số quan sát trong bảng \(2 \times 2\).
Vì OR > 0 và phân phối của nó thường lệch phải, nên ta áp dụng phép biến đổi logarit:
\[ \log(\hat{OR}) \sim \mathcal{N} \left( \log(OR), \ \sigma^2 \right) \]
Trong đó:
\[ \hat{\sigma}^2 = \frac{1}{a} + \frac{1}{b} + \frac{1}{c} + \frac{1}{d} \]
Khi đó, khoảng tin cậy \((1 - \alpha)\) cho \(\log(OR)\) là:
\[ \log(\hat{OR}) \pm z_{1 - \alpha/2} \cdot \sqrt{\hat{\sigma}^2} \]
Và khoảng tin cậy cho OR là:
\[ CI_{1 - \alpha}(\hat{OR}) = \left[ \exp\left( \log(\hat{OR}) - z \cdot \sqrt{\hat{\sigma}^2} \right), \ \exp\left( \log(\hat{OR}) + z \cdot \sqrt{\hat{\sigma}^2} \right) \right] \]
Ví dụ: Mối liên hệ giữa loại hình quảng cáo và phản hồi khách hàng
Một công ty thử hai hình thức quảng cáo cho sản phẩm: Truyền hình (Nhóm 1) và Mạng xã hội (Nhóm 2). Kết quả khảo sát:
| Có phản hồi | Không phản hồi | Tổng | |
|---|---|---|---|
| Quảng cáo TV | 60 | 40 | 100 |
| Quảng cáo mạng XH | 30 | 70 | 100 |
Tính Odds Ratio và khoảng tin cậy bằng R
# Dữ liệu bảng 2x2
a <- 60; b <- 40
c <- 30; d <- 70
# Tính OR
OR_hat <- (a * d) / (b * c)
# Log(OR) và SE
logOR <- log(OR_hat)
SE_logOR <- sqrt(1/a + 1/b + 1/c + 1/d)
# Mức tin cậy
z <- qnorm(0.975) # z0.975 ≈ 1.96
# Khoảng tin cậy cho log(OR)
lower_log <- logOR - z * SE_logOR
upper_log <- logOR + z * SE_logOR
# Chuyển về khoảng tin cậy cho OR
CI_lower <- exp(lower_log)
CI_upper <- exp(upper_log)
# In kết quả
cat("Odds Ratio ước lượng:", round(OR_hat, 3), "\n")
## Odds Ratio ước lượng: 3.5
cat("Khoảng tin cậy 95% cho OR: [", round(CI_lower, 3), ",", round(CI_upper, 3), "]\n")
## Khoảng tin cậy 95% cho OR: [ 1.949 , 6.287 ]
Odds Ratio = 3.5: Xác suất có phản hồi từ quảng cáo TV gấp 3.5 lần so với quảng cáo mạng xã hội.
Khoảng tin cậy 95% không chứa 1: Mối liên hệ là có ý nghĩa thống kê ở mức 5%.
vd3 <- table(data$Gender,data$Homeowner)
vd3
##
## N Y
## F 2826 4344
## M 2789 4100
odds sở hữu nhà ở từng nhóm
\[ \text{Odds}_F = \frac{\text{Số sở hữu nhà}}{\text{Số không sở hữu nhà}} = \frac{4344}{2826} \approx 1.537 \]
\[ \text{Odds}_M = \frac{4100}{2789} \approx 1.470 \]
Odds Ratio (OR)
\[ OR = \frac{\text{Odds}_F}{\text{Odds}_M} = \frac{4344 / 2826}{4100 / 2789} = \frac{4344 \times 2789}{2826 \times 4100} \approx 1.046 \]
OR > 1 cho thấy việc là Nữ có xu hướng làm tăng odds sở hữu nhà so với Nam.
Cụ thể, odds sở hữu nhà của Nữ cao hơn Nam khoảng 4.6%.
Tuy nhiên, giá trị OR gần 1 cho thấy sự khác biệt về odds không lớn, cần phân tích thêm về ý nghĩa thống kê để kết luận chắc chắn.
Nhận định ban đầu từ phân tích bảng chéo và Relative Risk:
Từ bảng chéo và chỉ số Relative Risk (RR), ta có thể đưa ra các nhận định sơ bộ về mối liên hệ giữa hai biến định tính nhị phân. Cụ thể, RR giúp so sánh khả năng xảy ra của một sự kiện giữa hai nhóm, từ đó chỉ ra nhóm nào có xu hướng cao hoặc thấp hơn đối với biến kết quả. Bảng chéo cung cấp cái nhìn trực quan ban đầu về sự phân bố dữ liệu theo hai chiều biến số.
Hạn chế của bảng chéo và Relative Risk:
Dù là công cụ hữu ích để mô tả mối quan hệ ban đầu, hai thước đo này vẫn tồn tại những hạn chế quan trọng:
Bảng chéo chỉ mang tính mô tả, không xét đến phương sai, độ tin cậy hay ảnh hưởng của các biến gây nhiễu khác.
Relative Risk chỉ phù hợp trong nghiên cứu theo dõi (cohort study), khi có thể xác định rõ xác suất xảy ra sự kiện ở từng nhóm. Với dữ liệu lấy mẫu theo tỷ lệ cố định (ví dụ: điều tra chéo), RR có thể gây hiểu lầm.
Khi sự kiện là hiếm (rare event), RR và Odds Ratio sẽ gần giống nhau, nhưng khi không hiếm, RR và OR có thể khác biệt đáng kể — cần cẩn trọng khi diễn giải.
Không kiểm soát được ảnh hưởng đồng thời của các biến khác (confounding), do đó cần phân tích hồi quy (ví dụ: hồi quy logistic) để có cái nhìn đầy đủ và chính xác hơn.
Bảng ngẫu nhiên (contingency table) là một công cụ mô tả dữ liệu định tính theo hai biến phân loại. Mỗi ô trong bảng là kết quả của một biến cố xác suất. Dưới góc độ lý thuyết xác suất, các bảng này có thể được sinh ra từ các phân phối xác suất như phân phối đa thức (Multinomial) hoặc phân phối Poisson độc lập. Điều này cho phép ta áp dụng các phương pháp thống kê để kiểm định và ước lượng mối liên hệ giữa các biến.
Hiệu hai tỷ lệ (Difference in Proportions)
Hiệu hai tỷ lệ đo lường sự khác biệt về xác suất xảy ra một sự kiện giữa hai nhóm. Trong ví dụ này, ta so sánh tỷ lệ sở hữu nhà giữa Nữ và Nam:
\[ \Delta p = P(\text{Homeowner} = Y \mid \text{Gender} = F) - P(\text{Homeowner} = Y \mid \text{Gender} = M) \]
Nếu hiệu hai tỷ lệ > 0: Nữ có tỷ lệ sở hữu nhà cao hơn Nam.
Nếu hiệu hai tỷ lệ < 0: Nữ có tỷ lệ sở hữu nhà thấp hơn Nam.
Nếu hiệu = 0: Không có sự khác biệt giữa hai nhóm.
Dưới đây là cách tính hiệu hai tỷ lệ và khoảng tin cậy trong R
# Tính tỷ lệ sở hữu nhà theo giới tính
p_F <- vd3["F", "Y"] / sum(vd3["F", ])
p_M <- vd3["M", "Y"] / sum(vd3["M", ])
diff_p <- p_F - p_M
# Hiển thị kết quả
diff_p
## [1] 0.01070605
Kết quả cho thấy tỷ lệ sở hữu nhà ở nhóm Nữ cao hơn nhóm Nam khoảng 1.07%. Khoảng cách này khá nhỏ, cho thấy tỷ lệ sở hữu nhà giữa Nữ và Nam là gần bằng nhau, chỉ khác biệt rất nhẹ.
# Tính khoảng tin cậy 95% cho hiệu hai tỷ lệ
prop.test(x = c(vd3["F", "Y"], vd3["M", "Y"]),
n = c(sum(vd3["F", ]), sum(vd3["M", ])),
correct = FALSE)
##
## 2-sample test for equality of proportions without continuity correction
##
## data: c(vd3["F", "Y"], vd3["M", "Y"]) out of c(sum(vd3["F", ]), sum(vd3["M", ]))
## X-squared = 1.6788, df = 1, p-value = 0.1951
## alternative hypothesis: two.sided
## 95 percent confidence interval:
## -0.005489482 0.026901581
## sample estimates:
## prop 1 prop 2
## 0.6058577 0.5951517
Giả thuyết:
- \(H_0\) : Tỷ lệ sở hữu nhà của Nam và
Nữ là bằng nhau.
- \(H_a\) : Tỷ lệ sở hữu nhà của Nam và
Nữ khác nhau.
Kết quả kiểm định hai tỷ lệ
Kiểm định sự khác biệt giữa tỷ lệ sở hữu nhà của Nữ và Nam được thực hiện bằng kiểm định chi bình phương (2-sample test for equality of proportions):
Diễn giải:
Với p-value = 0.1951 > 0.05, chúng ta không đủ bằng chứng để bác bỏ giả thuyết \(H_0\) ở mức ý nghĩa 5%.
Điều này có nghĩa là, dựa trên dữ liệu hiện tại, tỷ lệ sở hữu nhà giữa Nữ và Nam không khác biệt có ý nghĩa thống kê.
Khoảng tin cậy 95% của hiệu tỷ lệ chứa giá trị 0, cho thấy sự khác biệt quan sát được có thể do ngẫu nhiên và không chắc chắn khác 0.
Mặc dù tỷ lệ sở hữu nhà của Nữ (60.59%) cao hơn Nam (59.52%) khoảng 1.07%, nhưng sự khác biệt này không đủ lớn và không đáng kể về mặt thống kê.
Tỷ số Nguy cơ (Relative Risk - RR)
Định nghĩa và cách tính
Tỷ số nguy cơ (Relative Risk - RR) là tỉ lệ xác suất xảy ra một kết quả (sự kiện) ở nhóm đối tượng 1 so với nhóm đối tượng 2.
Công thức tính RR dựa trên bảng 2x2 như sau:
\[ RR = \frac{P(\text{sự kiện} \mid \text{nhóm 1})}{P(\text{sự kiện} \mid \text{nhóm 2})} \]
Trong đó,
- \(P(\text{sự kiện} \mid
\text{nhóm})\) là tỷ lệ phần trăm (hoặc xác suất) xảy ra sự kiện
trong nhóm đó.
Ví dụ
Giả sử ta có bảng ngẫu nhiên với biến giới tính (Gender) và sở hữu nhà (Homeowner), RR được tính là:
\[ RR = \frac{P(\text{Sở hữu nhà} \mid \text{Nữ})}{P(\text{Sở hữu nhà} \mid \text{Nam})} = \frac{\text{Số Nữ sở hữu nhà} / \text{Tổng số Nữ}}{\text{Số Nam sở hữu nhà} / \text{Tổng số Nam}} \]
Diễn giải
Lưu ý
RR thể hiện tỷ lệ trực tiếp giữa hai xác suất, nên thường dễ hiểu hơn khi làm việc với dữ liệu y học hoặc kinh tế.
Tuy nhiên, RR chỉ có thể áp dụng khi xác suất (tỷ lệ) của kết quả có ý nghĩa rõ ràng (ví dụ: sự kiện xảy ra hay không) và các nhóm so sánh là độc lập.
RR khác với Odds Ratio (tỷ số chênh), cả hai đều đo lường mức độ liên quan nhưng có cách diễn giải và ứng dụng khác nhau.
Tỷ số Chênh (Odds Ratio - OR)
Định nghĩa Odds
Odds là tỷ lệ giữa xác suất xảy ra sự kiện và xác suất không xảy ra sự kiện:
\[ \text{Odds} = \frac{p}{1-p} \]
với \(p\) là xác suất của sự kiện.
Định nghĩa Odds Ratio
Odds Ratio (OR) là tỷ số giữa odds của kết quả ở nhóm 1 và odds của kết quả ở nhóm 2:
\[ OR = \frac{\text{Odds nhóm 1}}{\text{Odds nhóm 2}} = \frac{\frac{p_1}{1-p_1}}{\frac{p_2}{1-p_2}} \]
Cách tính OR từ bảng 2x2
Giả sử bảng 2x2 có dạng:
| Kết quả Y | Kết quả N | |
|---|---|---|
| Nhóm 1 | a | b |
| Nhóm 2 | c | d |
Công thức tính OR:
\[ OR = \frac{a \times d}{b \times c} \]
ví dụ:
vd4 <- table(data$Gender, data$Homeowner)
addmargins(vd4)
##
## N Y Sum
## F 2826 4344 7170
## M 2789 4100 6889
## Sum 5615 8444 14059
odds1 <- vd4["M", "Y"] / vd4["M", "N"]
odds2 <- vd4["F", "Y"] / vd4["F", "N"]
print(odds1)
## [1] 1.470061
print(odds2)
## [1] 1.537155
Odds của M (nam) ≈ 1.47: tức là trong nhóm nam, xác suất có kết quả “Y” gấp khoảng 1.47 lần “N”.
Odds của F (nữ) ≈ 1.54: trong nhóm nữ, xác suất “Y” gấp khoảng 1.54 lần “N”.
Diễn giải OR
Nếu \(OR = 1\), odds của kết quả ở hai nhóm bằng nhau.
Nếu \(OR > 1\), odds của kết quả ở nhóm 1 cao hơn nhóm 2. Ví dụ \(OR = 2\) nghĩa là odds của kết quả ở nhóm 1 gấp đôi nhóm 2.
Nếu \(OR < 1\), odds của kết quả ở nhóm 1 thấp hơn nhóm 2.
Lưu ý: OR không phải là tỷ lệ xác suất (risk), nên diễn giải cần cẩn thận, không giống như Relative Risk (RR). Ví dụ, \(OR = 2\) không đồng nghĩa xác suất ở nhóm 1 gấp 2 lần nhóm 2.
Khi nào OR xấp xỉ RR?
OR xấp xỉ RR khi sự kiện xảy ra là hiếm (xác suất nhỏ). Khi đó, odds gần bằng xác suất.
Tại sao OR quan trọng?
\[ OR(\text{nhóm 1 so với nhóm 2}) = \frac{1}{OR(\text{nhóm 2 so với nhóm 1})} \]
Ví dụ với dữ liệu siêu thị: Tính OR cho việc sở hữu nhà giữa Nữ và Nam
Giả sử ma trận dữ liệu:
# Tính Odds Ratio
OR <- (vd3["F","N"] * vd3["M","Y"]) / (vd3["F","Y"] * vd3["M","N"])
OR
## [1] 0.9563518
Giới thiệu cách tính
Khoảng tin cậy (KTC) cho OR thường được tính dựa trên biến đổi logarit của OR vì log(OR) có phân phối xấp xỉ chuẩn, giúp tính toán dễ dàng hơn.
Công thức tính KTC 95% cho \(\log(OR)\):
\[ \log(OR) \pm z_{0.975} \times SE_{\log(OR)} \]
Sau đó lấy mũ của khoảng trên để được KTC cho OR:
\[ \left( e^{\log(OR) - z_{0.975} SE}, \quad e^{\log(OR) + z_{0.975} SE} \right) \]
Trong đó:
- \(SE_{\log(OR)} = \sqrt{\frac{1}{a} +
\frac{1}{b} + \frac{1}{c} + \frac{1}{d}}\), với \(a,b,c,d\) là các ô trong bảng 2x2.
- \(z_{0.975} \approx 1.96\) là giá trị
tới hạn của phân phối chuẩn cho mức ý nghĩa 5%.
Tính khoảng tin cậy cho OR trong R
library(DescTools)
# Tính Odds Ratio cùng khoảng tin cậy 95%
result <- OddsRatio(vd3, conf.level = 0.95)
print(result)
## odds ratio lwr.ci upr.ci
## 0.9563518 0.8939173 1.0231469
Diễn giải khoảng tin cậy:
Nếu khoảng tin cậy chứa giá trị 1, điều đó có nghĩa là không có sự khác biệt rõ rệt về odds giữa hai nhóm với mức ý nghĩa 5%.
Nếu toàn bộ khoảng tin cậy lớn hơn 1, odds ở nhóm 1 cao hơn nhóm 2 một cách có ý nghĩa.
Nếu toàn bộ khoảng tin cậy nhỏ hơn 1, odds ở nhóm 1 thấp hơn nhóm 2 một cách có ý nghĩa.
library(epitools)
vd4 <- table(data$Gender, data$Homeowner)
addmargins(vd4)
##
## N Y Sum
## F 2826 4344 7170
## M 2789 4100 6889
## Sum 5615 8444 14059
riskratio(vd4)
## $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"
Chọn một cặp biến nhị phân khác từ bộ dữ liệu Supermarket Transactions là MaritalStatus và Homeowner và xem xét mối liên hệ giữa MaritalStatus và Homeowner.
vd1 <- table(data$MaritalStatus, data$Homeowner)
addmargins(vd1)
##
## N Y Sum
## M 1719 5147 6866
## S 3896 3297 7193
## Sum 5615 8444 14059
# Tổng từng nhóm
total_M <- sum(vd1["M", ])
total_S <- sum(vd1["S", ])
# Tỷ lệ sở hữu nhà (Y) theo nhóm
p_M <- vd1["M", "Y"] / total_M
p_S <- vd1["S", "Y"] / total_S
# Hiệu hai tỷ lệ
diff_prop <- p_S - p_M
diff_prop
## [1] -0.2912736
Hiệu hai tỷ lệ (Difference in Proportions) = -0.2913. Nghĩa là tỷ lệ sở hữu nhà của nhóm S thấp hơn nhóm M khoảng 29.13%. Đây là sự chênh lệch khá lớn và âm cho thấy nhóm S có tỷ lệ sở hữu nhà thấp hơn.
# Relative Risk (RR)
RR <- p_S / p_M
RR
## [1] 0.6114466
Tỷ số nguy cơ (Relative Risk, RR) = 0.6114, RR < 1 có nghĩa là khả năng sở hữu nhà của nhóm S chỉ bằng khoảng 61% so với nhóm M, hay nói cách khác, nhóm S có nguy cơ thấp hơn để sở hữu nhà
# Odds Ratio (OR)
OR <- (vd1["S","Y"] * vd1["M","N"]) / (vd1["S","N"] * vd1["M","Y"])
OR
## [1] 0.2826322
Tỷ số chênh (Odds Ratio, OR) = 0.2826, OR < 1 cho thấy odds sở hữu nhà ở nhóm S chỉ bằng khoảng 28% odds của nhóm M. Giá trị này nhỏ hơn RR vì OR thường “kéo” xa hơn về 0 hoặc vô cùng khi sự kiện không phổ biến hoặc tỷ lệ khác biệt lớn.
# Khoảng tin cậy 95% cho OR
SE_log_OR <- sqrt(1/vd1["S","Y"] + 1/vd1["S","N"] + 1/vd1["M","Y"] + 1/vd1["M","N"])
z <- 1.96
log_OR <- log(OR)
lower_CI <- exp(log_OR - z * SE_log_OR)
upper_CI <- exp(log_OR + z * SE_log_OR)
print(c(lower_CI, upper_CI))
## [1] 0.2630926 0.3036231
Khoảng tin cậy 95% cho OR: (0.2631, 0.3036). Khoảng này không chứa 1, nên sự khác biệt odds là có ý nghĩa thống kê rất rõ ràng.