library(csv)
data <- read.csv("D:/UFM/2025- Kì 2/Phân tích dữ liệu định tính - Trần Mạnh Tường/Supermarket Transactions.csv", header = T)
Bộ dữ liệu “Supermarket Transactions” ghi nhận thông tin chi tiết về các giao dịch mua hàng tại một siêu thị trong một khoảng thời gian nhất định. Mỗi dòng dữ liệu đại diện cho một giao dịch, bao gồm nhiều thông tin liên quan đến khách hàng (giới tính, loại thành viên, chi nhánh mua hàng), thông tin sản phẩm (loại sản phẩm, kênh thanh toán), và các biến liên quan đến hành vi mua sắm (thời gian mua hàng, mức độ hài lòng, tổng giá trị đơn hàng,…).
Supermarket Transactions là file csv ,nên ta đọc từ file csv.
Thao tác thực hiện: Ta gán bộ dữ liệu Supermarket Transactions với tên là data.
Để có thể kiểm tra cấu trúc tổng quát của dữ liệu, ta sử dụng lệnh
str()
Lệnh str() là viết tắt của structure – dùng để:
Kiểm tra cấu trúc tổng quát của một đối tượng, thường là một data frame.
Giúp ta nhận biết được:
Số lượng dòng, số lượng cột.
Tên cụ thể của các biến.
Kiểu dữ liệu của từng biến.
Một vài giá trị mẫu đầu tiên của từng biến.
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 ...
Từ kết quả hiển thị, ta thấy:
Dữ liệu bao gồm: 14,059 dòng (obs) và 16 biến (variables).
Tên cụ thể của từng biến, kiểu dữ liệu và một số giá trị mẫu.
Mục tiêu của phân tích này là áp dụng các kỹ thuật thống kê mô tả và thống kê suy diễn để khám phá các đặc điểm của khách hàng và hành vi mua sắm của họ, với trọng tâm là các biến định tính (categorical variables). bao gồm:
Gender: Giới tính (F - Nữ, M - Nam)
MaritalStatus: Tình trạng hôn nhân (S - Độc thân, M
- Đã kết hôn)
Homeowner: Có sở hữu nhà hay không (Y – Có, N –
Không)
AnnualIncome: Thu nhập hàng năm (được biểu thị dưới
dạng các khoảng)
City, StateorProvince,
Country: Thông tin địa lý
ProductFamily, ProductDepartment,
ProductCategory: Phân loại sản phẩm
Trong R, 2 hàm thường được sử dụng cho mục đích kiểm tra một cách
trực quan các dòng đầu và cuối của bộ dữ liệu là head() và
tail().
Hai câu lệnh này giúp khi phân tích:
Nhanh chóng xác nhận dữ liệu đã được nhập đúng định dạng (kiểu ngày tháng, ký tự, số, v.v.).
Kiểm tra tính đầy đủ, nhất quán của dữ liệu từ đầu đến cuối.
Phát hiện sớm các lỗi phổ biến như: dữ liệu bị cắt xén, dòng trống, dữ liệu sai vị trí…
head(data,5)
| X | PurchaseDate | CustomerID | Gender | MaritalStatus | Homeowner | Children | AnnualIncome | City | StateorProvince | Country | ProductFamily | ProductDepartment | ProductCategory | UnitsSold | Revenue |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2007-12-18 | 7223 | F | S | Y | 2 | $30K - $50K | Los Angeles | CA | USA | Food | Snack Foods | Snack Foods | 5 | 27.38 |
| 2 | 2007-12-20 | 7841 | M | M | Y | 5 | $70K - $90K | Los Angeles | CA | USA | Food | Produce | Vegetables | 5 | 14.90 |
| 3 | 2007-12-21 | 8374 | F | M | N | 2 | $50K - $70K | Bremerton | WA | USA | Food | Snack Foods | Snack Foods | 3 | 5.52 |
| 4 | 2007-12-21 | 9619 | M | M | Y | 3 | $30K - $50K | Portland | OR | USA | Food | Snacks | Candy | 4 | 4.44 |
| 5 | 2007-12-22 | 1900 | F | S | Y | 3 | $130K - $150K | Beverly Hills | CA | USA | Drink | Beverages | Carbonated Beverages | 4 | 14.00 |
Câu lệnh head(data,5) giúp hiển thị 5 dòng đầu tiên, mặc
định sẽ hiển thị từ dòng 1 đến dòng 5. Nếu muốn thay đổi số dòng hiển
thị thì chỉ cần điền một con số khác trong câu lệnh là được.
Mục đích của câu lệnh:
Xem cấu trúc dữ liệu ban đầu, định dạng biến, kiểu dữ liệu.
Kiểm tra nhập liệu đầu dòng có hợp lý không.
Phù hợp để xác định xem dữ liệu có được đọc đúng cách (ví dụ: ngày, ký tự, số…).
tail(data,5)
| X | PurchaseDate | CustomerID | Gender | MaritalStatus | Homeowner | Children | AnnualIncome | City | StateorProvince | Country | ProductFamily | ProductDepartment | ProductCategory | UnitsSold | Revenue | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 14055 | 14055 | 2009-12-29 | 9102 | F | M | Y | 2 | $10K - $30K | Bremerton | WA | USA | Food | Baking Goods | Baking Goods | 3 | 9.64 |
| 14056 | 14056 | 2009-12-29 | 4822 | F | M | Y | 3 | $10K - $30K | Walla Walla | WA | USA | Food | Frozen Foods | Vegetables | 3 | 7.45 |
| 14057 | 14057 | 2009-12-31 | 250 | M | S | Y | 1 | $30K - $50K | Portland | OR | USA | Drink | Beverages | Pure Juice Beverages | 4 | 3.24 |
| 14058 | 14058 | 2009-12-31 | 6153 | F | S | N | 4 | $50K - $70K | Spokane | WA | USA | Drink | Dairy | Dairy | 2 | 4.00 |
| 14059 | 14059 | 2009-12-31 | 3656 | M | S | N | 3 | $50K - $70K | Portland | OR | USA | Non-Consumable | Household | Electrical | 5 | 25.53 |
Ngược lại với head là tail, câu lệnh tail(data,5) giúp
hiển thị 5 dòng cuối cùng của dữ liệu. Nếu muốn thay đổi số dòng hiển
thị thì cũng chỉ cần điền một con số khác trong câu lệnh.
Mục đích của câu lệnh:
Kiểm tra kết thúc tập dữ liệu, xem dữ liệu có bị thiếu hoặc lỗi định dạng ở cuối không.
Kiểm tra tính đồng nhất và nhất quán đến cuối tập dữ liệu.
Để kiểm tra tính hoàn chỉnh của dữ liệu, cụ thể là phát hiện giá trị bị thiếu (NA) trong bộ dữ liệu, ta dùng các câu lệnh sau:
sum(is.na(data))
## [1] 0
is,na() là câu lệnh giúp đánh dấu dữ liệu đang bị
thiếu.
Kết quả sẽ là TRUE nếu trong dữ liệu có giá trị
thiếu NA.
Kết quả sẽ là FALSE nếu không thiếu.
sum(is,na()) sẽ giúp ta tính tổng giá trị bị thiếu
(nếu có).
Vì TRUE được tính là 1, FALSE là 0 nên
tổng của các TRUE sẽ là số lượng phần tử bị thiếu.
Mục đích câu lệnh giúp nhanh chóng biết được toàn bộ dataset có bao nhiêu giá trị bị thiếu.
which(is.na(data))
## integer(0)
which(is.na(data)) đang tìm vị trí các phần tử bị thiếu
trong toàn bộ data.
integer(0) có nghĩa là không có bất kỳ giá trị
nào bị thiếu trong toàn bộ dữ liệu.Nếu có giá trị bị thiếu xuất hiện trong bộ dữ liệu, ta có thể dùng
lệnh na.omit() để loại bỏ tất cả các hàng trong data có
chứa ít nhất một giá trị bị thiếu.
Bảng thống kê tần số của biến Gender - giới tính như sau:
table(data$Gender)
##
## F M
## 7170 6889
Lệnh table() giúp tạo ra một bảng tần số đếm số lần
xuất hiện của từng giá trị trong biến của data
Nhận xét: Dựa trên bảng tần số, dữ liệu có tổng cộng 14.059 quan sát, trong đó có 7.170 người thuộc giới tính nữ (F - Female) và 6.889 người thuộc giới tính nam (M - Male), cho thấy số lượng nữ chiếm ưu thế nhẹ so với nam.
table(data$Gender)/sum(nrow(data))
##
## F M
## 0.5099936 0.4900064
Ta giải thích các lệnh thực hiện ra bảng kết quả tần suất như sau:
Lệnh table(data$Gender) trả về số lượng từng nhóm như đã giải thích bên trên
Lệnh nrow(data) hiển thị tổng số quan sát trong dataframe
Ta lấy số lượng từng nhóm chia cho tổng số quan sát của nhóm đó sẽ ra tuần suất
Nhận xét: Dựa trên bảng tần suất, tỷ lệ Nữ - F chiếm khoảng 50,99%, còn tỷ lệ Nam - M cũng có tỷ gần 49%. Sự chênh lệch giữa 2 giới tính là không quá đáng kể
Sau khi thấy bảng tấn số và tần suất về giới tính, ta tiến hành trực quan hóa bằng biểu đồ tròn dưới đây:
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)
data %>% group_by(Gender) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Gender)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
labs(caption = "Biểu đồ tròn về tần số giới tính") +
theme_void()
Giải thích các câu lệnh như sau:
data: là dataframe gốc chứa dữ liệu.
%>%: toán tử pipe dùng để truyền kết quả bước
trước sang bước sau.
group_by(Gender): nhóm dữ liệu theo biến giới
tính.
summarise(n = n()): đếm số lượng người trong từng
nhóm giới tính và gán vào biến mới là n.
ggplot(): hàm tạo biểu đồ với khung dữ liệu đầu
vào.
x = '': trục x rỗng vì không cần thiết trong biểu đồ
tròn.
y = n: giá trị số lượng dùng để chia tỷ lệ các
phần.
fill = Gender: tô màu khác nhau cho từng giới
tính.
geom_col(color = ''): tô viền ngoài cho từng
phần.
coord_polar('y'): Chuyển hệ trục từ Cartesian sang
Polar tạo ra biểu đồ tròn và xoay theo trục y để chuyển từ cột thành
vòng tròn.
geom_text(aes(x = 1.3, label = n), position = position_stack(vjust = 0.5)):
Hiển thị các con số thống kê cụ thể bên trong các phần của biểu đồ, x =
1.3 là vị trí các nhãn lệch ra một chút khỏi tâm, position_stack(vjust):
căn giữa các nhãn theo chiều dọc trong từng phần tròn.
labs(caption = " "): Thêm dòng chú thích phía dưới
biểu đồ.
theme_void(): Dùng xóa toàn bộ trục, lưới, nhãn, để
biểu đồ tròn hiển thị gọn gàng và tập trung vào nội dung chính.
Nhận xét: Biểu đồ tròn trên thể hiện tần số phân bố giới tính trong bộ dữ liệu. Có thể thấy, phần màu đỏ đại diện cho giới tính nữ (F) chiếm tỷ lệ lớn hơn một chút so với phần màu xanh dương đại diện cho giới tính nam (M). Mặc dù sự khác biệt không lớn, nhưng biểu đồ cho thấy giới tính nữ có xu hướng chiếm ưu thế nhẹ so với giới tính nam trong tập dữ liệu này. Biểu đồ trực quan này giúp dễ dàng so sánh và nhận diện sự chênh lệch nhỏ giữa hai nhóm giới tính.
Bảng thống kê tần số của biến MaritalStatus - tình trạng hôn nhân như sau:
table(data$MaritalStatus)
##
## M S
## 6866 7193
table(data$MaritalStatus)/sum(nrow(data))
##
## M S
## 0.4883704 0.5116296
data %>%
group_by(MaritalStatus) %>% summarise(n = n()) %>%
mutate(perc = round(n / sum(n) * 100, 1)) %>%
ggplot(aes(x = "", y = perc, fill = MaritalStatus)) +
geom_col(color = 'black') +
coord_polar("y") +
geom_text(aes(x = 1.3, label = paste0(perc, "%")),
position = position_stack(vjust = 0.5)) +
labs(caption = "Biểu đồ tròn về tần suất tình trạng hôn nhân") +
theme_void()
Giải thích các câu lệnh sẽ tương tự như biểu đồ trên, bên cạnh đó cũng có các câu lệnh mới như sau:
mutate(perc = round(n / sum(n) * 100, 1)): tính phần
trăm và làm tròn 1 chữ số thập phân.
y = perc: biểu đồ dựa trên tần suất % thay vì số
lượng.
label = paste0(perc, "%"): hiển thị phần trăm trong
biểu đồ.
Nhận xét: Biểu đồ tròn trên thể hiện tần suất về tình trạng hôn nhân, ta thấy phần màu xanh trên biểu đồ chiếm % nhiều hơn so với màu đó. Điều đó đồng nghĩa những người còn độc thân chiếm số lượng nhiều hơn đã kết hôn.
Kết quả thống kê tần số và tấn suất của biến Homeowner - sở hữu nhà hay không như sau:
table(data$Homeowner)
##
## N Y
## 5615 8444
table(data$Homeowner)/sum(nrow(data))
##
## N Y
## 0.3993883 0.6006117
Nhận xét: Dựa vào bảng tần số và tần suất của biến Homeowner – sở hữu nhà hay không, có thể thấy trong tổng số dữ liệu, có 8.444 người sở hữu nhà (ký hiệu Y) và 5.615 người không sở hữu nhà (ký hiệu N). Tính theo tỷ lệ, khoảng 60,06% số người trong tập dữ liệu là chủ sở hữu nhà, trong khi khoảng 39,94% còn lại không có nhà.
data %>% group_by(Homeowner) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Homeowner)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
labs(caption = "Biểu đồ tròn về tỷ lệ sở hữu nhà") +
theme_void()
Kết quả thống kê tần số và tấn suất của biến AnnualIncome - Thu nhập hàng năm (được biểu thị dưới dạng các khoảng) như sau:
table(data$AnnualIncome)
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 3090 643 760 273 4601
## $50K - $70K $70K - $90K $90K - $110K
## 2370 1709 613
table(data$AnnualIncome)/sum(nrow(data))
##
## $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
data %>% group_by(AnnualIncome) %>% summarise(n = n()) %>%
ggplot(aes(x = n, y = AnnualIncome))+
geom_col(fill='lightblue')+
labs(y = "Các mức thu nhập hằng năm", x="tần số")+
labs(caption = "Biểu đồ tần số mức thu nhập hằng năm")+
geom_text(aes(label =n), vjust=0, color = 'black')
Nhận xét: Nhìn chung, phần lớn thu nhập trong bộ dữ liệu khoảng từ 30.000 đến 50.000 USD/năm, với 4.601 người, chiếm tỷ lệ cao nhất trong tất cả các nhóm. Theo sau đó là nhóm thu nhập từ 10.000 đến 30.000 USD với 3.090 người và nhóm 50.000 đến 70.000 USD với 2.370 người. Nhóm thu nhập từ 70.000 đến 90.000 USD và 90.000 đến 110.000 USD có số lượng lần lượt là 1.709 và 613 người. Trong khi đó, các nhóm thu nhập cao hơn như 130.000–150.000 USD và trên 150.000 USD có tần số thấp hơn đáng kể, với lần lượt 760 và 273 người, cho thấy số người có thu nhập rất cao chiếm tỷ lệ nhỏ. Biểu đồ này phản ánh xu hướng phổ biến là phần lớn người lao động có mức thu nhập trung bình, trong khi số người có thu nhập rất cao hoặc rất thấp tương đối ít.
Kết quả thống kê tần số và tấn suất của biến City - Thành phố của các khách hàng có trong bộ dữ liệu như sau:
table(data$City)
##
## 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
table(data$City)/sum(nrow(data))
##
## 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
data %>% group_by(City) %>% summarise(n = n()) %>%
ggplot(aes(x = n, y = City))+
geom_col(fill='pink')+
labs(x="tần số", y = "Thông tin thành phố mà các khách hàng đang sống")+
labs(caption = "Biểu đồ tần số các thành phố mà các khách hàng đang sống")+
geom_text(aes(label =n), vjust=0.5, color = 'black')
Nhận xét: Biểu đồ cho thấy tần số khách hàng theo các thành phố nơi họ đang sinh sống. Thành phố có số lượng khách hàng cao nhất là San Andres với 1.386 người, tiếp theo là Seattle (1.257) và Los Angeles (926). Một số thành phố khác như Spokane, San Francisco, Merida cũng có lượng khách hàng đáng kể (trên 800 người). Ngược lại, các thành phố như Guadalajara (75), San Francisco (130) và Walla Walla (160) có số lượng khách hàng thấp nhất. Điều này cho thấy sự phân bố khách hàng không đồng đều, tập trung nhiều ở các thành phố lớn.
Kết quả thống kê tần số và tấn suất của biến StateorProvince - Tiểu bang của các khách hàng đang sinh sống có trong bộ dữ liệu như sau:
table(data$StateorProvince)
##
## BC CA DF Guerrero Jalisco OR Veracruz WA
## 809 2733 815 383 75 2262 464 4567
## Yucatan Zacatecas
## 654 1297
table(data$StateorProvince)/sum(nrow(data))
##
## BC CA DF Guerrero Jalisco OR
## 0.057543211 0.194395049 0.057969984 0.027242336 0.005334661 0.160893378
## Veracruz WA Yucatan Zacatecas
## 0.033003770 0.324845295 0.046518245 0.092254072
library(scales)
data %>% group_by(StateorProvince) %>% summarise(n = n()) %>%
mutate(percent = n / sum(n)) %>%
ggplot(aes(x = percent, y = reorder(StateorProvince, percent))) +
geom_col(fill = 'yellow') +
scale_x_continuous(labels = percent_format(accuracy = 0.01)) +
geom_text(aes(label = paste0(round(percent * 100, 2), "%")),
hjust = -0.1, color = 'black') +
labs(x = "Tỷ lệ (%)", y = "Tiểu bang", caption = "Biểu đồ tỷ lệ (%) các khách hàng theo tiểu bang") +
theme_minimal()
mutate(percent = n / sum(n)): tính tỷ lệ phần trăm
của từng tiểu bang so với tổng và sau đó lưu vào cột percent.
ggplot(aes(x = percent, y = reorder(StateorProvince, percent))):
Tạo biểu đồ với trục hoành là percent và trục tung
là tên tiểu bang
reorder(StateorProvince, percent): sắp xếp tiểu bang
theo thứ tự phần trăm tăng dần.
Tùy chỉnh trụ x
scale_x_continuous(labels = percent_format(accuracy = 0.01)):
Hiển thị theo định dạng phần trăm %.
accuracy = 0.01: làm tròn đến 2 chữ số sau dấu
phẩy.
geom_text(aes(label = paste0(round(percent * 100, 2), "%")), hjust = -0.1, color = 'black'):
Thêm nhãn phần trăm phía ngoài cột.
round(percent * 100, 2): làm tròn tỷ lệ phần trăm 2
chữ số.
hjust = -0.1: chỉnh vị trí nhãn ra phía ngoài
cột.
color = 'black': màu chữ là đen.
Kết quả thống kê tần số và tấn suất của biến Country - Quốc gia của các khách hàng đang sống có trong bộ dữ liệu như sau:
table(data$Country)
##
## Canada Mexico USA
## 809 3688 9562
table(data$Country)/sum(nrow(data))
##
## Canada Mexico USA
## 0.05754321 0.26232307 0.68013372
data %>% group_by(Country) %>% summarise(n = n()) %>%
ggplot(aes(x = Country, y = n))+
geom_col(fill='darkorange')+
labs(x = "Quốc gia", y="tần số")+
labs(caption = "Biểu đồ tần số quốc gia")+
geom_text(aes(label =n), vjust=2, color = 'black')
Kết quả thống kê tần số và tấn suất của biến ProductFamily - Sản phẩm tiêu dùng gia đình như sau:
table(data$ProductFamily)
##
## Drink Food Non-Consumable
## 1250 10153 2656
table(data$ProductFamily)/sum(nrow(data))
##
## Drink Food Non-Consumable
## 0.08891102 0.72217085 0.18891813
data %>% group_by(ProductFamily) %>% summarise(n = n()) %>%
ggplot(aes(x = ProductFamily, y = n))+
geom_col(fill='forestgreen')+
labs(x = "Sản phẩm tiêu dùng gia đình", y="tần số")+
labs(caption = "Biểu đồ tần suất giới tính")+
geom_text(aes(label = paste0(round(table(data$ProductFamily)/sum(nrow(data)), 3), "%")),hjust = 0.3,vjust=2, color = 'black')
Kết quả thống kê tần số và tấn suất của biến ProductDepartment - Bộ phận sản phẩm
table(data$ProductDepartment)
##
## 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
table(data$ProductDepartment)/sum(nrow(data))
##
## 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
data %>% group_by(ProductDepartment) %>% summarise(n = n()) %>%
ggplot(aes(x = n, y = ProductDepartment))+
geom_col(fill='orchid')+
labs(x="tần số", y = "Thông tin về bộ phận sản phẩm")+
labs(caption = "Biểu đồ tần số bộ phận sản phẩm")+
geom_text(aes(label =n), vjust=0.5, color = 'black')
Kết quả thống kê tần số và tấn suất của biến ProductCategory - Danh mục sản phẩm
table(data$ProductCategory)
##
## 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
table(data$ProductCategory)/sum(nrow(data))
##
## 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
data %>% group_by(ProductCategory) %>% summarise(n = n()) %>%
ggplot(aes(x = n, y = ProductCategory))+
geom_col(fill='gray')+
labs(x="tần số", y = "Thông tin về các sản phẩm cụ thể")+
labs(caption = "Biểu đồ tần số các sản phẩm")+
geom_text(aes(label =n), vjust=0.5, color = 'black')
Ta chọn 3 hạng mục từ 3 biến của danh sách các biến định tính trên, bao gồm:
Hạng mục “F” của biến Gender - giới tính
Hạng mục “S” của biến MaritalStatus - tình trạng hôn nhân
Hạng mục “USA” của biến Country - quốc gia
Ta muốn ước lượng khoảng tin cậy 95% cho tỷ lệ nữ (Gender = “F”)
# Số người là nữ
n_female <- sum(data$Gender == "F")
# Tổng số quan sát
n_total <- nrow(data)
# Ước lượng khoảng tin cậy 95% cho tỷ lệ nữ
prop.test(n_female, n_total, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: n_female out of n_total, 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
Tỷ lệ khách hàng là nữ ước lượng được là: 0.5099 hay 50.99%
Khoảng tin cậy 95% cho tỷ lệ này: [50.17%, 51.82%]
Nhận xét: Từ các quan sát cho thấy tỷ lệ khách hàng nữ được ước lượng là khoảng 51.0%. Khoảng tin cậy 95% cho tỷ lệ này là từ 50.2% đến 51.8%, không bao gồm 50%. Với p-value = 0.0182 < 0.05, ta bác bỏ giả thuyết rằng tỷ lệ nữ bằng 50%. Điều này cho thấy có bằng chứng thống kê rằng tỷ lệ khách hàng nữ khác 50%, và cao hơn một chút so với giả thuyết.
Ta đặt bài toán giả thiết:
Giả thuyết H0: Tỷ lệ nữ trong tổng thể = 0.5
Giả thuyết H1: Tỷ lệ nữ ≠ 0.5
Kết quả thu được:
Nếu p-value < 0.05 ⇒ bác bỏ H0 ⇒ tỷ lệ nữ ≠ 50%, có ý nghĩa thống kê.
Nếu p-value ≥ 0.05 ⇒ không bác bỏ H0, không đủ bằng chứng để nói tỷ lệ nữ khác 50%.
→ Vì p-value = 0.0182 < 0.05, bác bỏ giả thuyết H0 ở mức ý nghĩa 5%.
Kết quả kiểm định giả thuyết cho thấy tỷ lệ khách hàng nữ trong mẫu khác 50% với độ tin cậy 95% (p-value = 0.0182 < 0.05). Do đó, có thể kết luận rằng tỷ lệ khách hàng nữ trong tổng thể không phải là 50%, mà là cao hơn một chút (~51%).
Trong toàn bộ dữ liệu khách mua hàng tại siêu thị, tỷ lệ khách hàng là nữ là khoảng 51%. Kết quả kiểm định cho thấy có bằng chứng thống kê rõ ràng rằng tỷ lệ này khác 50% — tức là không hoàn toàn cân bằng giữa nam và nữ. Mặc dù chênh lệch chỉ khoảng 1%, nhưng vì dữ liệu lớn, sự khác biệt nhỏ này cũng có ý nghĩa.
Ta muốn ước lượng khoảng tin cậy 95% cho tỷ lệ độc thân (MaritalStatus = “S”)
# Số người độc thân
n_single <- sum(data$MaritalStatus == "S")
# Ước lượng khoảng tin cậy 95% cho tỷ lệ độc thân
prop.test(n_single, n_total, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: n_single out of n_total, 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
Tỷ lệ khách hàng độc thân ước lượng được là: 0.5116 hay 51.16%
Khoảng tin cậy 95% cho tỷ lệ này: [50.33%, 51.99%]
Nhận xét: Ta tin tưởng 95% rằng tỷ lệ khách hàng độc thân trong tổng thể nằm trong khoảng từ 50.33% đến 51.99%. Mặc dù khoảng này khá hẹp (chênh lệch chỉ ~1.6%), nó cho thấy khách độc thân chiếm tỉ lệ nhỉnh hơn một chút so với khách đã kết hôn hoặc ở trạng thái khác.
Ta đặt bài toán giả thiết:
Giả thuyết H0: Tỷ lệ khách độc thân = 50%
Giả thuyết H1: Tỷ lệ khách độc thân ≠ 50%
Kết quả giá trị p-value = 0.00597 < 0.05 ⇒ Bác bỏ giả thuyết H0
Có bằng chứng thống kê cho thấy tỷ lệ khách hàng độc thân KHÁC 50%, Tỷ lệ thực tế cao hơn một chút (~51.16%).
# Số người sống ở USA
n_USA <- sum(data$Country == "USA")
# Ước lượng khoảng tin cậy 95% cho tỷ lệ sống ở USA
prop.test(n_USA, n_total, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: n_USA out of n_total, null probability 0.5
## X-squared = 1824, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.6723397 0.6878289
## sample estimates:
## p
## 0.6801337
Tỷ lệ khách hàng sống tại USA ước lượng được là: 0.6801337 hay 68.01%
Khoảng tin cậy 95% cho tỷ lệ này là: [67.23%, 68.79%]
Nhận xét: Ta có thể tin tưởng 95% rằng tỷ lệ khách hàng sống tại Hoa Kỳ (USA) trong tổng thể là từ 67.23% đến 68.79%. Tức là gần 7 trong 10 khách hàng trong dữ liệu là người sống tại Mỹ.
Ta đặt bài toán giả thiết:
Giả thuyết H0: Tỷ lệ khách hàng sống ở USA = 50%
Giả thuyết H1: Tỷ lệ khách hàng sống ở USA ≠ 50%
Kết quả giá trị p-value < 2.2e-16 (rất nhỏ, gần như bằng 0) ⇒ Bác bỏ giả thuyết H0 ở mức ý nghĩa 5%
Có bằng chứng thống kê rất mạnh cho thấy tỷ lệ khách hàng sống ở Mỹ KHÁC 50% — và thực tế là cao hơn rất nhiều (68%).
Ta chọn 3 cặp biến định tính như sau:
Gender và Homeowner
MaritalStatus và Homeowner
Country và ProductFamily
Ta tạo bảng tần suất chéo (contingency table) cho hai biến Gender và Homeowner như sau:
# Bảng tần suất chéo
table_gender_home <- table(data$Gender, data$Homeowner)
table_gender_home
##
## N Y
## F 2826 4344
## M 2789 4100
Kết quả của bảng tần suất này có ý nghĩa như sau:
Có 2826 nữ không sở hữu nhà.
Có 4344 nữ sở hữu nhà.
Có 2789 nam không sở hữu nhà.
Có 4100 nam sở hữu nhà.
# Hiển thị bảng tần suất chéo theo tỷ lệ hàng
prop.table(table_gender_home, margin = 1)
##
## N Y
## F 0.3941423 0.6058577
## M 0.4048483 0.5951517
Lệnh prop.table(..., margin = 1) có ý nghĩa như sau:
Tính tỷ lệ phần trăm (proportion) theo hàng trong bảng table_gender_home.
margin = 1: tỷ lệ theo từng giới tính (F và M).
Tổng mỗi hàng sẽ bằng 1.0 (100%).
Diễn giải kết quả:
Trong số nữ sẽ có ~39.41% không sở hữu nhà và ~60.59% sở hữu nhà.
Trong số nam sẽ có ~40.48% không sở hữu nhà và ~59.52% sở hữu nhà.
Nhận xét: Dựa trên kết quả bảng tần suất và tỷ lệ, ta có thể rút ra một số nhận định rằng trong 7170 nữ giới (2826 không sở hữu nhà và 4344 sở hữu nhà), và 6889 nam giới (2789 không sở hữu nhà và 4100 sở hữu nhà). Tỷ lệ sở hữu nhà giữa nam và nữ khá tương đồng, nhưng nữ có xu hướng sở hữu nhà cao hơn một chút (60.59% so với 59.52%).
Ta trực quan hóa bảng tần suất thành biểu đồ cột chồng như sau:
# Trực quan hóa bằng biểu đồ cột chồng
ggplot(data, aes(x = Gender, fill = Homeowner)) +
geom_bar(position = "fill") +
labs(title = "Tỷ lệ sở hữu nhà theo giới tính", y = "Tỷ lệ", x = "Giới tính") +
scale_y_continuous(labels = scales::percent)
Nhận xét: Biểu đồ thể hiện tỷ lệ sở hữu nhà theo giới tính cho thấy sự phân bố tương đối đồng đều giữa nam và nữ. Cụ thể, cả hai giới đều có khoảng 60% người sở hữu nhà và khoảng 40% không sở hữu nhà. Điều này cho thấy rằng giới tính không phải là một yếu tố ảnh hưởng rõ rệt đến khả năng sở hữu nhà trong tập dữ liệu này. Mặc dù tỷ lệ phụ nữ sở hữu nhà có phần nhỉnh hơn so với nam giới, nhưng mức chênh lệch là rất nhỏ và không thể hiện một xu hướng rõ ràng.
Ta thực hiện kiểm định Chi-squared như sau:
chisq.test(table_gender_home)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table_gender_home
## X-squared = 1.6344, df = 1, p-value = 0.2011
Giả thuyết kiểm định:
Giả thuyết không H0: Hai biến Gender và Homeowner là độc lập với nhau (tức giới tính không ảnh hưởng đến khả năng sở hữu nhà).
Giả thuyết đối H1: Hai biến có mối liên hệ với nhau (tức giới tính có ảnh hưởng đến khả năng sở hữu nhà).
Kết quả kiểm định Chi-bình phương:
Giá trị Chi-squared (X²): 1.6344
Bậc tự do df: 1
Giá trị p-value: 0.2011
Kết luận thống kê: Vì p = 0.2011 > 0.05, ta chấp nhận giả thuyết không. Điều này có nghĩa là không có bằng chứng thống kê đủ mạnh để kết luận rằng tồn tại mối liên hệ giữa giới tính và tình trạng sở hữu nhà.
Thảo luận thêm: Kết quả kiểm định thống kê phù hợp với những gì biểu đồ trực quan cho thấy: tỷ lệ sở hữu nhà giữa nam và nữ khá tương đồng (khoảng 60% ở cả hai giới). Mặc dù phụ nữ có vẻ nhỉnh hơn một chút về tỷ lệ sở hữu nhà, nhưng sự khác biệt đó là nhỏ và không mang ý nghĩa thống kê.
Cặp biến tiếp theo là Tình trạng hôn nhân và Sở hữu nhà, liệu có bao nhiêu người độc thân sở hữu nhà và bao nhiêu người đã kết hôn sở hữu nhà?
Ta xem kết quả bảng tần suất chéo như sau:
# Bảng tần suất chéo
table_marital_home <- table(data$MaritalStatus, data$Homeowner)
table_marital_home
##
## N Y
## M 1719 5147
## S 3896 3297
Kết quả của bảng tần suất này có ý nghĩa như sau:
Có 1719 người đã kết hôn không sở hữu nhà.
Có 5147 người đã kết hôn sở hữu nhà.
Có 3896 người độc thân không sở hữu nhà.
Có 3297 người độc thân sở hữu nhà.
# Hiển thị bảng tần suất chéo theo tỷ lệ hàng
prop.table(table_marital_home, margin = 1)
##
## N Y
## M 0.2503641 0.7496359
## S 0.5416377 0.4583623
Nhận xét: Phân tích bảng tần suất cho thấy có sự khác biệt rõ rệt trong việc sở hữu nhà giữa những người đã kết hôn và người độc thân. Cụ thể, trong tổng số 6866 người đã kết hôn, có đến 5147 người (tương đương 75%) sở hữu nhà, trong khi chỉ 1719 người (khoảng 25%) không sở hữu nhà. Ngược lại, trong nhóm 7193 người độc thân, tỷ lệ sở hữu nhà chỉ là 45.8% (3297 người), còn lại 54.2% (3896 người) không sở hữu nhà.
Những con số này cho thấy rằng người đã kết hôn có khả năng sở hữu nhà cao hơn đáng kể so với người độc thân. Điều này có thể phản ánh sự ổn định về mặt tài chính, sự chia sẻ chi phí sinh hoạt hoặc khả năng tiếp cận tín dụng tốt hơn ở những người đã kết hôn. Từ đó, có thể bước đầu nhận định rằng tình trạng hôn nhân có liên quan đến khả năng sở hữu nhà trong tập dữ liệu này.
# Trực quan hóa
data_summary <- data %>% group_by(MaritalStatus, Homeowner) %>% summarise(count = n()) %>% ungroup()
## `summarise()` has grouped output by 'MaritalStatus'. You can override using the
## `.groups` argument.
ggplot(data_summary, aes(x = MaritalStatus, y = count, fill = Homeowner)) +
geom_col(position = position_dodge()) +
geom_text(aes(label = count), position = position_dodge(width = 0.9), vjust = -0.5) +
labs(title = "Số lượng sở hữu nhà theo tình trạng hôn nhân", y = "Số lượng", x = "Tình trạng hôn nhân")
Giải thích câu lệnh:
group_by(MaritalStatus, Homeowner): Nhóm dữ liệu
theo tình trạng hôn nhân và tình trạng sở hữu nhà. Mỗi tổ hợp (ví dụ:
Độc thân + Có nhà, Kết hôn + Không nhà) sẽ thành 1 nhóm.
summarise(count = n()): Tính số lượng bản ghi trong
mỗi nhóm và đặt tên cột là count.
ungroup(): Bỏ grouping để kết quả không còn ràng
buộc bởi các nhóm nữa (tránh lỗi khi xử lý tiếp sau này).
Kết quả là một bảng tóm tắt (data_summary) gồm 3
cột: MaritalStatus, Homeowner, và count.
ggplot(data_summary, aes(...)): Tạo biểu đồ từ bảng
data_summary, trong đó:
x = MaritalStatus: trục hoành là tình trạng hôn nhân
(M, S).
y = count: chiều cao cột là số lượng.
fill = Homeowner: màu sắc cột thay đổi theo tình
trạng sở hữu nhà (Y, N).
geom_col(position = position_dodge()): Vẽ biểu đồ
cột (column chart) với các cột đặt cạnh nhau (thay vì chồng lên nhau)
theo từng nhóm Homeowner.
geom_text(...): Thêm nhãn số lượng trên mỗi cột:
label = count: hiện số lượng.
position_dodge(width = 0.9): căn chỉnh vị trí chữ
trùng khớp với vị trí các cột.
vjust = -0.5: dịch chữ lên phía trên một
chút.
labs(...): Đặt tiêu đề và tên trục:
title: tiêu đề biểu đồ.
x: tên trục hoành là “Tình trạng hôn nhân”.
y: tên trục tung là “Số lượng”.
Nhận xét: Biểu đồ cho thấy 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. Cụ thể, số người đã kết hôn sở hữu nhà là 5.147, gần gấp ba lần so với nhóm không sở hữu nhà. Ngược lại, trong nhóm độc thân, số người không sở hữu nhà (3.896) lại cao hơn so với người có nhà (3.297). Điều này cho thấy tình trạng hôn nhân có ảnh hưởng rõ rệt đến khả năng sở hữu nhà, có thể do người đã kết hôn thường có tài chính ổn định hơn và nhu cầu mua nhà để ổn định cuộc sống gia đình.
Ta thực hiện kiểm định Chi-squared như sau:
chisq.test(table_marital_home)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table_marital_home
## X-squared = 1241.2, df = 1, p-value < 2.2e-16
Giả thuyết kiểm định:
Giả thuyết không H0: Tình trạng hôn nhân và quyền sở hữu nhà là độc lập (không liên quan đến nhau).
Giả thuyết đối H1: Tình trạng hôn nhân và quyền sở hữu nhà có mối liên hệ (không độc lập).
Kết quả kiểm định Chi-bình phương:
Giá trị Chi-squared (X²): 1241.2
Bậc tự do df: 1
Giá trị p-value: < 2.2e-16
Kết luận thống kê: Vì giá trị p cực kỳ nhỏ (p < 2.2e-16), rất nhỏ hơn nhiều so với 0.05, ta bác bỏ giả thuyết không. Kết quả kiểm định cho thấy rằng có mối liên hệ có ý nghĩa thống kê mạnh mẽ giữa tình trạng hôn nhân và việc sở hữu nhà. Nói cách khác, khả năng một người sở hữu nhà có liên quan chặt chẽ đến việc họ có đang kết hôn hay không.
Thảo luận thêm: Tình trạng hôn nhân không chỉ là một đặc điểm xã hội, mà còn có ảnh hưởng rõ ràng đến kết quả kinh tế, cụ thể là khả năng sở hữu nhà. Sự khác biệt lớn về tỷ lệ và kết quả kiểm định thống kê cùng chỉ ra rằng người đã kết hôn có nhiều khả năng sở hữu nhà hơn người độc thân, có thể do yếu tố thu nhập kép, ổn định tài chính, hoặc kế hoạch cuộc sống dài hạn hơn.
Cặp biến cuối cùng là cặp biến Quốc gia và Nhóm sản phẩm chính
# Bảng tần suất chéo
table_country_product <- table(data$Country, data$ProductFamily)
table_country_product
##
## Drink Food Non-Consumable
## Canada 69 580 160
## Mexico 325 2683 680
## USA 856 6890 1816
Nhận xét:
Mỹ là quốc gia có số lượng cao nhất ở tất cả các nhóm sản phẩm, đặc biệt là nhóm Food (6890).
Mexico đứng thứ hai, với Food là nhóm chiếm nhiều nhất.
Canada có số lượng thấp nhất ở tất cả các nhóm, đặc biệt Drink chỉ có 69.
# Hiển thị bảng tần suất chéo theo tỷ lệ hàng
prop.table(table_country_product, margin = 1)
##
## Drink Food Non-Consumable
## Canada 0.08529048 0.71693449 0.19777503
## Mexico 0.08812364 0.72749458 0.18438178
## USA 0.08952102 0.72056055 0.18991843
Nhận xét: Dù số lượng tuyệt đối khác nhau, tỷ lệ phân bổ sản phẩm theo từng quốc gia lại khá giống nhau.
Cả ba quốc gia đều có:
Trên 70% sản phẩm là Food (chiếm tỷ lệ cao nhất).
Drink và Non-Consumable chiếm tỷ lệ thấp và gần tương đương nhau.
Canada có tỷ lệ sản phẩm Non-Consumable cao hơn một chút (19.8%) so với Mexico và USA.
USA có tỷ lệ sản phẩm Drink cao nhất (8.95%), nhưng chênh lệch là không đáng kể.
# Trực quan hóa
data_summary2 <- data %>% group_by(Country, ProductFamily) %>% summarise(count = n()) %>% mutate(total = sum(count), pct = count / total) %>% ungroup()
## `summarise()` has grouped output by 'Country'. You can override using the
## `.groups` argument.
ggplot(data_summary2, aes(x = Country, y = pct, fill = ProductFamily)) +
geom_col(position = position_dodge()) +
geom_text(aes(label = scales::percent(pct, accuracy = 0.1)),
position = position_dodge(width = 0.9), vjust = -0.3, size = 3) +
scale_y_continuous(labels = scales::percent_format()) +
labs(title = "Tỷ lệ nhóm sản phẩm theo quốc gia",
y = "Tỷ lệ",
x = "Quốc gia")
Giải thích câu lệnh:
group_by(Country, ProductFamily): Nhóm dữ liệu theo
Quốc gia và Nhóm sản phẩm
summarise(count = n()): Tính số lượng từng nhóm
(count)
mutate(total = sum(count): Tính tổng số sản phẩm
theo mỗi Quốc gia
pct = count / total): Tính tỷ lệ phần trăm cho từng
nhóm
ungroup(): Bỏ nhóm để tránh ảnh hưởng khi vẽ biểu
đồ
ggplot(): vẽ biểu đồ cột theo tỷ lệ quốc
gia
geom_col(position = position_dodge()): Vẽ các cột
với các nhóm (ProductFamily) đặt cạnh nhau thay vì chồng lên
nhau.
geom_text(aes(label = scales::percent(pct, accuracy = 0.1)), position = position_dodge(width = 0.9), vjust = -0.3, size = 3)
Gán nhãn văn bản là phần trăm, ví dụ “72.1%” thay vì số thập phân.
accuracy = 0.1 → hiển thị chính xác đến 1 chữ số
thập phân.
vjust = -0.3 → căn vị trí nhãn nằm phía trên đầu
cột.
size = 3 → chỉnh kích cỡ chữ.
scale_y_continuous(labels = scales::percent_format()):
Biến trục y thành định dạng phần trăm
Nhận xét: Nhóm sản phẩm “Food” chiếm tỷ lệ cao nhất ở cả 3 quốc gia, % tỷ lệ là cao hơn hẳn 2 nhóm còn lại.”Drink” và “Non-Consumable” có tỷ lệ thấp hơn và khá tương đồng giữa các quốc gia. Biểu đồ cho thấy cơ cấu nhóm sản phẩm gần như không thay đổi theo quốc gia, cho thấy tính đồng nhất trong danh mục sản phẩm hoặc hành vi tiêu dùng ở các thị trường này.
Ta thực hiện kiểm định Chi-squared như sau:
chisq.test(table_country_product)
##
## Pearson's Chi-squared test
##
## data: table_country_product
## X-squared = 1.1831, df = 4, p-value = 0.8809
Giả thuyết kiểm định:
Giả thuyết không H0: 2 biến Quốc gia và Nhóm sản phẩm chính là độc lập (không liên quan đến nhau).
Giả thuyết đối H1: 2 biến Quốc gia và Nhóm sản phẩm chính có mối liên hệ (không độc lập).
Kết quả kiểm định Chi-bình phương:
Giá trị Chi-squared (X²): 1.1831
Bậc tự do df: 4
Giá trị p-value: 0.8809
Kết luận thống kê: Vì giá trị p-value = 0.8809, tức rất lớn hơn mức ý nghĩa, do đó không đủ bằng chứng thống kê để bác bỏ giả thuyết H0. Không có mối liên hệ giữa các quốc gia và nhóm sản phẩm.
Giới tính: Cả nam và nữ đều là nhóm khách hàng chính, nhưng chưa có dấu hiệu khác biệt rõ rệt về hành vi mua sắm chỉ dựa vào giới tính.
Tình trạng hôn nhân & sở hữu nhà: Người đã kết hôn có tỷ lệ sở hữu nhà cao hơn đáng kể so với người độc thân. Điều này gợi ý rằng nhóm khách hàng đã lập gia đình có thể có tài chính ổn định và tiềm năng mua sắm cao hơn.
Quốc gia & nhóm sản phẩm chính: Ở cả 3 quốc gia (Canada, Mexico, USA), thực phẩm (Food) là nhóm sản phẩm chủ đạo, chiếm hơn 70% tổng lượng sản phẩm bán ra. Các nhóm Drink và Non-Consumable chiếm tỷ trọng thấp hơn, tương đối đồng đều giữa các nước.
Kiểm định thống kê: Kiểm định Chi-bình phương cho thấy không có sự khác biệt có ý nghĩa thống kê về cơ cấu nhóm sản phẩm giữa các quốc gia (p-value ≈ 0.88).
Giới hạn trong biến định tính: Phân tích chỉ dựa trên các biến định tính, chưa xem xét yếu tố định lượng như thu nhập, doanh thu, hoặc số lượng bán chi tiết theo thời gian.
Dữ liệu chưa chuẩn hóa hoàn toàn: Một số biến (ví dụ: thu nhập) vẫn ở dạng text, cần xử lý thêm để phục vụ phân tích sâu hơn.
Không có yếu tố thời gian rõ ràng: Mặc dù có ngày mua hàng, nhưng chưa phân tích theo xu hướng thời gian (ví dụ theo quý hoặc năm).
Chiến lược sản phẩm: Tập trung tiếp thị nhóm thực phẩm (Food) vì chiếm ưu thế trong cả ba thị trường. Tuy nhiên, cũng cần nghiên cứu thêm để tăng tỷ lệ tiêu thụ các nhóm sản phẩm còn lại.
Nhắm mục tiêu khách hàng: Ưu tiên nhóm khách hàng đã kết hôn và sở hữu nhà, vì có thể đây là đối tượng có sức mua cao và ổn định hơn.
Chiến dịch cá nhân hóa theo khu vực: Dù chưa có sự khác biệt đáng kể giữa các quốc gia, doanh nghiệp vẫn nên phân tích thêm theo thành phố hoặc tỉnh bang để điều chỉnh chiến lược cụ thể hơn.
Liệu có sự khác biệt đáng kể trong hành vi mua sắm giữa các nhóm thu nhập không?
Mức chi tiêu trung bình theo giới tính và tình trạng hôn nhân là bao nhiêu?
Có xu hướng theo mùa vụ nào trong hành vi mua sắm không?
Nên phân tích thêm tương quan giữa nhóm sản phẩm và doanh thu để tối ưu danh mục sản phẩm.