Phân tích dữ liệu và các biến định tính (nhiệm vụ 2)
# Tải các gói thư viện cần thiết
library(readxl) # Gói này dùng để đọc file Excel (.xls, .xlsx) vào R
## Warning: package 'readxl' was built under R version 4.4.3
library(DT) # Gói này cung cấp chức năng hiển thị bảng dữ liệu dạng tương tác (DataTable) trong R Markdown hoặc Shiny
## Warning: package 'DT' was built under R version 4.4.3
# Gán file dữ liệu
Supermarket_Transactions <- read_excel("D:/tai/Supermarket Transactions.xlsx")
## New names:
## • `` -> `...1`
# Hiển thị bảng dữ liệu
datatable(Supermarket_Transactions)
## Warning in instance$preRenderHook(instance): It seems your data is too big for
## client-side DataTables. You may consider server-side processing:
## https://rstudio.github.io/DT/server.html
str(Supermarket_Transactions)
## tibble [14,059 × 16] (S3: tbl_df/tbl/data.frame)
## $ ...1 : num [1:14059] 1 2 3 4 5 6 7 8 9 10 ...
## $ PurchaseDate : POSIXct[1:14059], format: "2007-12-18" "2007-12-20" ...
## $ CustomerID : num [1:14059] 7223 7841 8374 9619 1900 ...
## $ Gender : chr [1:14059] "F" "M" "F" "M" ...
## $ MaritalStatus : chr [1:14059] "S" "M" "M" "M" ...
## $ Homeowner : chr [1:14059] "Y" "Y" "N" "Y" ...
## $ Children : num [1:14059] 2 5 2 3 3 3 2 2 3 1 ...
## $ AnnualIncome : chr [1:14059] "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
## $ City : chr [1:14059] "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
## $ StateorProvince : chr [1:14059] "CA" "CA" "WA" "OR" ...
## $ Country : chr [1:14059] "USA" "USA" "USA" "USA" ...
## $ ProductFamily : chr [1:14059] "Food" "Food" "Food" "Food" ...
## $ ProductDepartment: chr [1:14059] "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
## $ ProductCategory : chr [1:14059] "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
## $ UnitsSold : num [1:14059] 5 5 3 4 4 3 4 6 1 2 ...
## $ Revenue : num [1:14059] 27.38 14.9 5.52 4.44 14 ...
Bộ dữ liệu được sử dụng trong phân tích này bao gồm 14.059 quan sát và 16 biến. Các biến trong bộ dữ liệu phản ánh thông tin nhân khẩu học, hành vi mua hàng và các đặc điểm liên quan đến khách hàng trong siêu thị. Cụ thể, các biến bao gồm:
…1: Số thứ tự
PurchaseDate: Ngày thực hiện giao dịch mua hàng.
CustomerID: Mã định danh duy nhất của khách hàng.
Gender: Giới tính của khách hàng (F: nữ, M: nam).
MaritalStatus: Tình trạng hôn nhân của khách hàng (S: độc thân, M: đã kết hôn).
Homeowner: Khách hàng có sở hữu nhà hay không (Y: có, N: không).
Children: Số lượng con cái của khách hàng.
AnnualIncome: Thu nhập hàng năm của khách hàng, được phân loại theo khoảng giá trị.
City: Thành phố cư trú của khách hàng.
StateorProvince: Bang hoặc tỉnh thành nơi khách hàng cư trú.
Country: Quốc gia của khách hàng.
ProductFamily: Nhóm sản phẩm chính, phân loại theo đặc tính chung.
ProductDepartment: Nhóm sản phẩm nằm trong sản phẩm chính, giúp phân loại sản phẩm cụ thể hơn.
ProductCategory: Danh mục cụ thể của sản phẩm, mô tả chi tiết hơn về loại mặt hàng.
UnitsSold: Số lượng đơn vị sản phẩm được bán trong giao dịch.
Revenue: Doanh thu thu được từ giao dịch.
Việc kiểm tra cấu trúc và xem trước dữ liệu cho thấy bộ dữ liệu đã được nhập thành công, các biến có tên rõ ràng và phù hợp, tạo nền tảng thuận lợi cho các bước phân tích kế tiếp.
head(Supermarket_Transactions)# Hiển thị các dòng đầu của dữ liệu
## # A tibble: 6 × 16
## ...1 PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## <dbl> <dttm> <dbl> <chr> <chr> <chr> <dbl>
## 1 1 2007-12-18 00:00:00 7223 F S Y 2
## 2 2 2007-12-20 00:00:00 7841 M M Y 5
## 3 3 2007-12-21 00:00:00 8374 F M N 2
## 4 4 2007-12-21 00:00:00 9619 M M Y 3
## 5 5 2007-12-22 00:00:00 1900 F S Y 3
## 6 6 2007-12-22 00:00:00 6696 F M Y 3
## # ℹ 9 more variables: AnnualIncome <chr>, City <chr>, StateorProvince <chr>,
## # Country <chr>, ProductFamily <chr>, ProductDepartment <chr>,
## # ProductCategory <chr>, UnitsSold <dbl>, Revenue <dbl>
tail(Supermarket_Transactions)# Hiển thị các dòng cuối của dữ liệu
## # A tibble: 6 × 16
## ...1 PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## <dbl> <dttm> <dbl> <chr> <chr> <chr> <dbl>
## 1 14054 2009-12-29 00:00:00 2032 F M N 3
## 2 14055 2009-12-29 00:00:00 9102 F M Y 2
## 3 14056 2009-12-29 00:00:00 4822 F M Y 3
## 4 14057 2009-12-31 00:00:00 250 M S Y 1
## 5 14058 2009-12-31 00:00:00 6153 F S N 4
## 6 14059 2009-12-31 00:00:00 3656 M S N 3
## # ℹ 9 more variables: AnnualIncome <chr>, City <chr>, StateorProvince <chr>,
## # Country <chr>, ProductFamily <chr>, ProductDepartment <chr>,
## # ProductCategory <chr>, UnitsSold <dbl>, Revenue <dbl>
Hai câu lệnh được dùng để hiển thị 6 dòng đầu và 6 dòng cuối của dữ liệu, nhằm hỗ trợ việc kiểm tra sơ bộ nội dung và định dạng các biến.
dt <- c("Gender", "Homeowner", "MaritalStatus","AnnualIncome", "City", "StateorProvince", "Country", "ProductFamily", "ProductDepartment","ProductCategory")
df_dt <- Supermarket_Transactions[,dt]
colSums(is.na(df_dt))
## Gender Homeowner MaritalStatus AnnualIncome
## 0 0 0 0
## City StateorProvince Country ProductFamily
## 0 0 0 0
## ProductDepartment ProductCategory
## 0 0
Dữ liệu cho thấy trong 10 biến được khảo sát, không có biến nào chứa giá trị thiếu (NA).
df <- lapply(df, function(x) { if(is.character(x)) factor(x) else x})# lapply() áp dụng hàm cho từng cột trong df_dt.
Dòng lệnh sau thực hiện việc chuyển đổi tất cả các cột có kiểu dữ
liệu character trong df_dt
thành kiểu
factor, giữ nguyên các cột khác không đổi.
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(knitr)
## Warning: package 'knitr' was built under R version 4.4.3
library(scales)
## Warning: package 'scales' was built under R version 4.4.3
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.4.3
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
# Tạo bảng tóm tắt
df_1 <- df_dt %>%
count(Gender, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`), label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Hiển thị bảng
df_1 %>%
select(Gender, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Giới tính", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.1 Phân phối theo giới tính - GENDER"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Giới tính | Tần số | Tỷ lệ (%) |
---|---|---|
F | 7170 | 50.9994 |
M | 6889 | 49.0006 |
Vậy trong bộ dữ liệu có 50.9993598% nữ và 49.0006402% nam
library(dplyr)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(RColorBrewer)
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.4.3
##
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
# Biểu đồ tròn (Pie chart)
p1 <- ggplot(df_1, aes(x = "", y = percent, fill = Gender)) +
geom_col(width = 1, color = "black") +
coord_polar(theta = "y") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 4) +
labs(title = "Tỷ lệ (%) mua hàng theo giới tính") +
scale_fill_brewer(palette = "Set3") +
theme_void()
# Biểu đồ cột Tần số
p2 <- ggplot(df_1, aes(x = Gender, y = `Tần số`, fill = Gender)) +
geom_col(width = 0.6, color = "black") +
geom_text(aes(label = `Tần số`), vjust = -0.5) +
labs(title = "Tần số mua hàng (Gender)", x = "Giới tính", y = "Số lượng") +
scale_fill_brewer(palette = "Set3") +
theme_minimal()
# Hiển thị cả hai biểu đồ cạnh nhau
grid.arrange(p1, p2, ncol = 2)
Kết quá cho thấy tỷ lệ nữ chiếm ưu thế hơn nam, với mức chênh lệch giới tính khoảng 1.9987197% (281 đơn hàng).
# Tạo bảng tóm tắt
df_2 <- df_dt %>%
count(Homeowner, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`), label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Hiển thị bảng
df_2 %>%
select(Homeowner, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Sở hữu nhà", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.2 Phân phối theo chủ sở hữu nhà"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Sở hữu nhà | Tần số | Tỷ lệ (%) |
---|---|---|
N | 5615 | 39.9388 |
Y | 8444 | 60.0612 |
Vậy trong bộ dữ liệu có 39.9388292% người không sở hữu nhà và 60.0611708% người sở hữu nhà.
# Biểu đồ tròn (Pie chart)
p3 <- ggplot(df_2, aes(x = "", y = percent, fill = Homeowner)) +
geom_col(width = 1, color = "black") +
coord_polar(theta = "y") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 4) +
labs(title = "Tỷ lệ (%) khách hàng sở hữu nhà") +
scale_fill_brewer(palette = "Set2") +
theme_void()
# Biểu đồ cột Tần số
p4 <- ggplot(df_2, aes(x = Homeowner, y = `Tần số`, fill = Homeowner)) +
geom_col(width = 0.6, color = "black") +
geom_text(aes(label = `Tần số`), vjust = -0.5) +
labs(title = "Tần số mua hàng (Homeowner)", x = "Sở hữu nhà", y = "Số lượng") +
scale_fill_brewer(palette = "Set2") +
theme_minimal()
# Hiển thị cả hai biểu đồ cạnh nhau
grid.arrange(p3, p4, ncol = 2)
Kết quả cho thấy phần lớn người mua hàng là chủ sở hữu nhà, với sự chênh lệch khoảng 20.1223416% khá cao so với nhóm không sở hữu nhà, chênh lệch khoảng 2.828 đơn hàng trong khoảng thời gian thống kê.
# Tạo bảng tóm tắt
df_3 <- df_dt %>%
count(MaritalStatus, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`), label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Hiển thị bảng
df_3 %>%
select(MaritalStatus, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Tình trạng hôn nhân", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.3 Phân phối theo tình trạng hôn nhân"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Tình trạng hôn nhân | Tần số | Tỷ lệ (%) |
---|---|---|
M | 6866 | 48.837 |
S | 7193 | 51.163 |
Vậy trong bộ dữ liệu có tỷ lệ 48.8370439% đã kết hôn và 51.1629561% chưa kết hôn/ độc thân.
# Biểu đồ tròn (Pie chart)
p5 <- ggplot(df_3, aes(x = "", y = percent, fill = MaritalStatus)) +
geom_col(width = 1, color = "black") +
coord_polar(theta = "y") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 4) +
labs(title = "Tỷ lệ (%) khách hàng đã/chưa kết hôn") +
scale_fill_brewer(palette = "Set1") +
theme_void()
# Biểu đồ cột Tần số
p6 <- ggplot(df_3, aes(x = MaritalStatus, y = `Tần số`, fill = MaritalStatus)) +
geom_col(width = 0.6, color = "black") +
geom_text(aes(label = `Tần số`), vjust = -0.5) +
labs(title = "Tần số mua hàng (MaritalStatus)", x = "Sở hữu nhà", y = "Số lượng") +
scale_fill_brewer(palette = "Set1") +
theme_minimal()
# Hiển thị cả hai biểu đồ cạnh nhau
grid.arrange(p5, p6, ncol = 2)
Kết quả cho thấy người độc thân có tỷ lệ/Tần số mua hàng cao hơn, với sự chênh lệch khoảng 2.3259122% với số khách hàng đã lập gia đình, chênh lệch khoảng 327 đơn hàng trong khoảng thời gian thống kê.
# Tạo bảng tóm tắt
df_4 <- df_dt %>%
count(AnnualIncome, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_4 %>%
select(AnnualIncome, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Tình trạng hôn nhân", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.4 Phân phối theo thu nhập hằng năm"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Tình trạng hôn nhân | Tần số | Tỷ lệ (%) |
---|---|---|
$10K - $30K | 3090 | 21.9788 |
$110K - $130K | 643 | 4.5736 |
$130K - $150K | 760 | 5.4058 |
$150K + | 273 | 1.9418 |
$30K - $50K | 4601 | 32.7264 |
$50K - $70K | 2370 | 16.8575 |
$70K - $90K | 1709 | 12.1559 |
$90K - $110K | 613 | 4.3602 |
Dữ liệu khảo sát ghi nhận 8 khoảng thu nhập khác nhau, bao gồm:
ggplot(df_4, aes(x = reorder(AnnualIncome, -`Tần số`), y = `Tần số`, fill = AnnualIncome)) +
geom_col(width = 0.5, color = "black") +
geom_text(
aes(label = paste0(`Tần số`, " (", scales::percent(percent, accuracy = 0.1), ")")),
vjust = -0.5, size = 3, color = "black"
) +
labs(
title = "Thu nhập hàng năm của khách hàng",
x = "Thu nhập",
y = "Số lượng"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
legend.position = "none" )
Kết quả phân tích cho thấy phần lớn khách hàng tập trung trong nhóm thu nhập từ $10K đến $90K, nổi bật nhất là nhóm có thu nhập $30K–$50K, chiếm tỷ trọng cao nhất. Tuy nhiên, khi thu nhập tăng lên, đặc biệt từ mức $90K trở đi, số lượng khách hàng có xu hướng giảm đáng kể. Đáng chú ý, nhóm khách hàng có thu nhập từ $150K trở lên là nhóm có tỷ lệ mua hàng thấp nhất trong toàn bộ mẫu khảo sát.
Sự chênh lệch giữa hai nhóm thu nhập này là rất lớn, cụ thể: tỷ lệ khách hàng thuộc nhóm $150K+ thấp hơn nhóm $90K–$120K là 30.7845508%, tương ứng với 4,328 đơn hàng trong giai đoạn thống kê.
# Tạo bảng tóm tắt
df_5 <- df_dt %>%
count(Country, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_5 %>%
select(Country, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Quốc gia", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.5 Phân phối theo quốc gia"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Quốc gia | Tần số | Tỷ lệ (%) |
---|---|---|
Canada | 809 | 5.7543 |
Mexico | 3688 | 26.2323 |
USA | 9562 | 68.0134 |
Dữ liệu khảo sát được thu thập từ 3 quốc gia khác nhau, bao gồm:
# Biểu đồ tròn (Pie chart)
p7 <- ggplot(df_5, aes(x = "", y = percent, fill = Country)) +
geom_col(width = 1, color = "black") +
coord_polar(theta = "y") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 4) +
labs(title = "Tỷ lệ (%) khách hàng đến từ các quốc gia") +
scale_fill_brewer(palette = "Dark2") +
theme_void()
# Biểu đồ cột Tần số
p8 <- ggplot(df_5, aes(x = Country, y = `Tần số`, fill = Country)) +
geom_col(width = 0.6, color = "black") +
geom_text(aes(label = `Tần số`), vjust = -0.5) +
labs(title = "Tần số mua hàng (Country)", x = "Sở hữu nhà", y = "Số lượng") +
scale_fill_brewer(palette = "Dark2") +
theme_minimal()
# Hiển thị cả hai biểu đồ cạnh nhau
grid.arrange(p7, p8, ncol = 2)
Kết quả phân tích cho thấy thị phần khách hàng đến từ Hoa Kỳ (USA) chiếm tỷ trọng lớn nhất, vượt hơn một nửa tổng số đơn hàng được thống kê. Ngược lại, Canada là quốc gia có số lượng đơn hàng thấp nhất trong ba quốc gia được khảo sát.
Mức chênh lệch về số lượng đơn hàng giữa Hoa Kỳ và Canada là rất lớn, lên tới 62.2590511% tương đương khoảng 8.753 đơn hàng trong thời gian thống kê.
# Tạo bảng tóm tắt
df_6 <- df_dt %>%
count(StateorProvince, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_6 %>%
select(StateorProvince, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Bang/Tỉnh", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.6 Phân phối theo bang/tỉnh"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Bang/Tỉnh | Tần số | Tỷ lệ (%) |
---|---|---|
BC | 809 | 5.7543 |
CA | 2733 | 19.4395 |
DF | 815 | 5.7970 |
Guerrero | 383 | 2.7242 |
Jalisco | 75 | 0.5335 |
OR | 2262 | 16.0893 |
Veracruz | 464 | 3.3004 |
WA | 4567 | 32.4845 |
Yucatan | 654 | 4.6518 |
Zacatecas | 1297 | 9.2254 |
Dữ liệu khảo sát ghi nhận tại 9 Bang/ tỉnh khác nhau từ 3 quốc gia, bao gồm:
ggplot(df_6, aes(x = reorder(StateorProvince, -`Tần số`), y = `Tần số`, fill = StateorProvince)) +
geom_col(width = 0.5, color = "black") +
geom_text(
aes(label = paste0(`Tần số`, " (", scales::percent(percent, accuracy = 0.1), ")")),
vjust = -0.5, size = 3, color = "black"
) +
labs(
title = "Phân bố khách hàng theo Bang/Tỉnh",
x = "Bang/Tỉnh",
y = "Số lượng"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
legend.position = "none" )
Kết quả phân tích theo từng bang/tỉnh cho thấy sự chênh lệch đáng kể về lượng đơn hàng giữa các khu vực. Cụ thể, bang WA ghi nhận số lượng đơn hàng cao nhất, trong khi Jalisco là địa phương có lượng đơn hàng thấp nhất. Mức chênh lệch giữa hai khu vực này là khoảng 31.9510634% tương đương khoảng 4.567 đơn hàng trong thời gian thống kê.
# Tạo bảng tóm tắt
df_7 <- df_dt %>%
count(City, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_7 %>%
select(City, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Thành phố", "Tần số", "Tỷ lệ (%)"),
caption = "Bảng 2.7 Phân phối theo thành phố",
align = "c" ) %>% kable_styling(
bootstrap_options = c("striped", "hover"), full_width = FALSE, position = "center" )
Thành phố | Tần số | Tỷ lệ (%) |
---|---|---|
Acapulco | 383 | 2.7242 |
Bellingham | 143 | 1.0171 |
Beverly Hills | 811 | 5.7685 |
Bremerton | 834 | 5.9321 |
Camacho | 452 | 3.2150 |
Guadalajara | 75 | 0.5335 |
Hidalgo | 845 | 6.0104 |
Los Angeles | 926 | 6.5865 |
Merida | 654 | 4.6518 |
Mexico City | 194 | 1.3799 |
Orizaba | 464 | 3.3004 |
Portland | 876 | 6.2309 |
Salem | 1386 | 9.8585 |
San Andres | 621 | 4.4171 |
San Diego | 866 | 6.1598 |
San Francisco | 130 | 0.9247 |
Seattle | 922 | 6.5581 |
Spokane | 875 | 6.2238 |
Tacoma | 1257 | 8.9409 |
Vancouver | 633 | 4.5025 |
Victoria | 176 | 1.2519 |
Walla Walla | 160 | 1.1381 |
Yakima | 376 | 2.6744 |
Dữ liệu khảo sát ghi nhận tại 23 thành phố khác nhau từ 3 quốc gia, sơ lược:
ggplot(df_7, aes(x = reorder(City, -`Tần số`), y = `Tần số`, fill = City)) +
geom_col(width = 0.5, color = "black") +
geom_text(
aes(label = scales::percent(percent, accuracy = 0.1)),
vjust = -0.5, size = 3, color = "black"
) +
labs(
title = "Phân bố khách hàng theo thành phố",
x = "Thành phố",
y = "Số lượng"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
legend.position = "none" )
Kết quả phân tích theo từng thành phố cho thấy sự chênh lệch đáng kể về lượng đơn hàng giữa các khu vực. Cụ thể, thành phố Salem ghi nhận số lượng đơn hàng cao nhất, trong khi Guadalajara là địa phương có lượng đơn hàng thấp nhất. Mức chênh lệch giữa hai khu vực này là khoảng 9.3249876% tương đương khoảng 1.311 đơn hàng trong thời gian thống kê.
# Tạo bảng tóm tắt
df_8 <- df_dt %>%
count(ProductFamily, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_8 %>%
select(ProductFamily, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Thành phố", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.8 Phân phối theo nhóm sản phẩm chính"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Thành phố | Tần số | Tỷ lệ (%) |
---|---|---|
Drink | 1250 | 8.8911 |
Food | 10153 | 72.2171 |
Non-Consumable | 2656 | 18.8918 |
Dữ liệu khảo sát được xếp vào từ 3 nhóm sản phẩm chính, bao gồm:
# Biểu đồ tròn (Pie chart)
p9 <- ggplot(df_8, aes(x = "", y = percent, fill = ProductFamily)) +
geom_col(width = 1, color = "black") +
coord_polar(theta = "y") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 4) +
labs(title = "Tỷ lệ (%) lựa chọn nhóm sản phẩm chính") +
scale_fill_brewer(palette = "Accent") +
theme_void()
# Biểu đồ cột Tần số
p10 <- ggplot(df_8, aes(x = ProductFamily, y = `Tần số`, fill = ProductFamily)) +
geom_col(width = 0.6, color = "black") +
geom_text(aes(label = `Tần số`), vjust = 0) +
labs(title = "Tần số mua hàng (ProductFamily)", x = "Nhóm sản phẩm chính", y = "Số lượng") +
scale_fill_brewer(palette = "Accent") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Hiển thị cả hai biểu đồ cạnh nhau
grid.arrange(p9, p10, ncol = 2)
Kết quả phân tích cho thấy thị phần khách hàng sẽ mua nhóm sản phẩm chính là Food chiếm tỷ trọng lớn nhất, vượt hơn một nửa tổng số đơn hàng được thống kê. Ngược lại, nhóm sản phẩm Non-Consumable có số lượng đơn hàng thấp nhất trong ba quốc gia được khảo sát.
Mức chênh lệch về số lượng đơn hàng giữa hai nhóm sản phẩm này là rất lớn, lên tới 53.3252721% tương đương khoảng 8.903 đơn hàng trong thời gian thống kê.
# Tạo bảng tóm tắt
df_9 <- df_dt %>%
count(ProductDepartment, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_9 %>%
select(ProductDepartment, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Bộ phận sản phẩm", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.9 Phân phối theo bộ phận sản phẩm"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Bộ phận sản phẩm | Tần số | Tỷ lệ (%) |
---|---|---|
Alcoholic Beverages | 356 | 2.5322 |
Baked Goods | 425 | 3.0230 |
Baking Goods | 1072 | 7.6250 |
Beverages | 680 | 4.8368 |
Breakfast Foods | 188 | 1.3372 |
Canned Foods | 977 | 6.9493 |
Canned Products | 109 | 0.7753 |
Carousel | 59 | 0.4197 |
Checkout | 82 | 0.5833 |
Dairy | 903 | 6.4229 |
Deli | 699 | 4.9719 |
Eggs | 198 | 1.4084 |
Frozen Foods | 1382 | 9.8300 |
Health and Hygiene | 893 | 6.3518 |
Household | 1420 | 10.1003 |
Meat | 89 | 0.6330 |
Periodicals | 202 | 1.4368 |
Produce | 1994 | 14.1831 |
Seafood | 102 | 0.7255 |
Snack Foods | 1600 | 11.3806 |
Snacks | 352 | 2.5037 |
Starchy Foods | 277 | 1.9703 |
Dữ liệu khảo sát được xếp vào 22 nhóm (bộ phận sản phẩm) khác nhau từ 3 nhóm sản phẩm chính, sơ lược:
ggplot(df_9, aes(x = reorder(ProductDepartment, -`Tần số`), y = `Tần số`, fill = ProductDepartment)) +
geom_col(width = 0.5, color = "black") +
geom_text(
aes(label = scales::percent(percent, accuracy = 0.1)),
vjust = -0.5, size = 3, color = "black"
) +
labs(
title = "Nhu cầu khách hàng theo từng bộ phận sản phẩm",
x = "Bộ phận sản phẩm",
y = "Số lượng"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
legend.position = "none" )
Kết quả phân tích theo các nhóm sản phẩm phụ (hoặc bộ phận sản phẩm) cho thấy sự chênh lệch đáng kể về số lượng đơn hàng giữa các nhóm. Nhóm sản phẩm Produce ghi nhận số lượng đơn hàng cao nhất, trong khi nhóm Carousel là nhóm có lượng đơn hàng thấp nhất. Mức chênh lệch giữa hai nhóm này ước tính khoảng 13.7634256% tương đương khoảng 1.935 đơn hàng trong thời gian thống kê.
# Tạo bảng tóm tắt
df_10 <- df_dt %>%
count(ProductCategory, name = "Tần số") %>%
mutate(
percent = `Tần số` / sum(`Tần số`),
label = percent(percent, accuracy = 0.1),
`Tỷ lệ (%)` = round(percent * 100, 4) )
# Chỉ chọn các cột cần hiển thị
df_10 %>%
select(ProductCategory, `Tần số`, `Tỷ lệ (%)`) %>%
kable(
format = "html",
col.names = c("Danh mục sản phẩm cụ thể", "Tần số", "Tỷ lệ (%)"),
align = "c",
caption = "Bảng 2.10 Phân phối theo danh mục sản phẩm cụ thể"
) %>%
kable_styling(c("striped", "hover"), full_width = FALSE, position = "center")
Danh mục sản phẩm cụ thể | Tần số | Tỷ lệ (%) |
---|---|---|
Baking Goods | 484 | 3.4426 |
Bathroom Products | 365 | 2.5962 |
Beer and Wine | 356 | 2.5322 |
Bread | 425 | 3.0230 |
Breakfast Foods | 417 | 2.9661 |
Candles | 45 | 0.3201 |
Candy | 352 | 2.5037 |
Canned Anchovies | 44 | 0.3130 |
Canned Clams | 53 | 0.3770 |
Canned Oysters | 35 | 0.2490 |
Canned Sardines | 40 | 0.2845 |
Canned Shrimp | 38 | 0.2703 |
Canned Soup | 404 | 2.8736 |
Canned Tuna | 87 | 0.6188 |
Carbonated Beverages | 154 | 1.0954 |
Cleaning Supplies | 189 | 1.3443 |
Cold Remedies | 93 | 0.6615 |
Dairy | 903 | 6.4229 |
Decongestants | 85 | 0.6046 |
Drinks | 135 | 0.9602 |
Eggs | 198 | 1.4084 |
Electrical | 355 | 2.5251 |
Frozen Desserts | 323 | 2.2975 |
Frozen Entrees | 118 | 0.8393 |
Fruit | 765 | 5.4414 |
Hardware | 129 | 0.9176 |
Hot Beverages | 226 | 1.6075 |
Hygiene | 197 | 1.4012 |
Jams and Jellies | 588 | 4.1824 |
Kitchen Products | 217 | 1.5435 |
Magazines | 202 | 1.4368 |
Meat | 761 | 5.4129 |
Miscellaneous | 42 | 0.2987 |
Packaged Vegetables | 48 | 0.3414 |
Pain Relievers | 192 | 1.3657 |
Paper Products | 345 | 2.4539 |
Pizza | 194 | 1.3799 |
Plastic Products | 141 | 1.0029 |
Pure Juice Beverages | 165 | 1.1736 |
Seafood | 102 | 0.7255 |
Side Dishes | 153 | 1.0883 |
Snack Foods | 1600 | 11.3806 |
Specialty | 289 | 2.0556 |
Starchy Foods | 277 | 1.9703 |
Vegetables | 1728 | 12.2911 |
Dữ liệu khảo sát được xếp vào 45 nhóm (danh mục sản phẩm cụ thể) khác nhau từ 3 nhóm sản phẩm chính, sơ lược:
ggplot(df_10, aes(x = reorder(ProductCategory, -`Tần số`), y = `Tần số`, fill = ProductCategory)) +
geom_col(width = 0.5, color = "black") +
geom_text(
aes(label = scales::percent(percent, accuracy = 0.1)),
vjust = 0, size = 2.5, color = "black", angle = 90, hjust = 0
) +
labs(
title = "Nhu cầu khách hàng theo từng danh mục sản phẩm cụ thể",
x = "Danh mục sản phẩm cụ thể",
y = "Số lượng"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
legend.position = "none" )
Kết quả phân tích theo từng danh mục sản phẩm cụ thể cho thấy sự chênh lệch đáng kể về số lượng đơn hàng giữa các nhóm. Sản phẩm Vegetables ghi nhận số lượng đơn hàng cao nhất, trong khi Canned Oysters là sản phẩm có lượng đơn hàng thấp nhất. Mức chênh lệch giữa hai nhóm này ước tính khoảng 12.0421083% tương đương khoảng 1.693 đơn hàng trong thời gian thống kê.
Giả sử biến ngẫu nhiên chuẩn tắc chuẩn \(Z \sim N(0,1)\). Với một mức xác suất \(p \in (0,1)\), giá trị tới hạn \(z_p\) được định nghĩa sao cho:
\[ P(Z > z_p) = p \quad \text{hay tương đương} \quad \Phi(z_p) = 1 - p \]
trong đó \(\Phi(z_p)\) là hàm phân phối tích lũy (CDF) của phân phối chuẩn.
Khi thực hiện \(n\) phép thử độc lập theo phân phối Bernoulli với xác suất thành công chưa biết là \(p\). Gọi \(x\) là số lần thành công trong \(n\) phép thử này. Khi đó, tỷ lệ mẫu (sample proportion) được ước lượng bởi:
\[ \hat{p} = \frac{x}{n} \]
Tỷ lệ mẫu \(\hat{p}\) là một ước lượng không chệch của \(p\) và được dùng làm cơ sở cho việc xây dựng khoảng tin cậy và thực hiện kiểm định giả thuyết cho tỷ lệ thành công thực sự trong tổng thể.
Với mức ý nghĩa \(\alpha\) ( thông thường 95%, 99%, 90%), khoảng tin cậy \(100(1 - \alpha)\%\) cho tỷ lệ \(p\) được tính bằng công thức:
\[ \left[ \hat{p} - z_{\alpha/2} \cdot \sqrt{ \frac{\hat{p}(1 - \hat{p})}{n} }, \quad \hat{p} + z_{\alpha/2} \cdot \sqrt{ \frac{\hat{p}(1 - \hat{p})}{n} } \right] \]
Trong đó:
Trong thống kê, kiểm định giả thuyết cho tỷ lệ thường dùng để xác định xem tỷ lệ mẫu \(\hat{p}\) có khác biệt một cách có ý nghĩa thống kê so với một tỷ lệ giả định \(p_0\) trong tổng thể.
# Hàm tính khoảng tin cậy cho tỷ lệ mẫu
conf_int_prop <- function(x, n, conf.level = 0.95) {
p_hat <- x / n # tỷ lệ lấy mẫu
alpha <- 1 - conf.level
z_crit <- qnorm(1 - alpha/2) # giá trị tới hạn z_alpha/2
SE <- sqrt(p_hat * (1 - p_hat) / n) # sai số chuẩn (standard error)
ME <- z_crit * SE # biên sai số (margin of error)
lower <- p_hat - ME
upper <- p_hat + ME
data <- c(p_hat, z_crit, ME, lower, upper)
names(data) <- c("Tỷ lệ mẫu", "Z tới hạn", "Sai số biên", "CI lower", "CI upper")
return(data)}
Gender <- sum(df_dt$Gender == "F")
conf_int_prop(Gender, nrow(df_dt), 0.95)
## Tỷ lệ mẫu Z tới hạn Sai số biên CI lower CI upper
## 0.509993598 1.959963985 0.008263311 0.501730287 0.518256910
Dựa trên kết quả phân tích, tỷ lệ mẫu của giới tính nữ trong tập dữ liệu đạt khoảng 51%. Với mức độ tin cậy 95%, ta có thể kết luận rằng tỷ lệ nữ trong toàn bộ quần thể mà mẫu đại diện nằm trong khoảng từ 50.17% đến 51.83%.
Khoảng tin cậy này khá hẹp, phản ánh rằng cỡ mẫu được sử dụng là đủ lớn và tỷ lệ ước lượng có độ chính xác cao, với sai số biên chỉ khoảng 0.8%. Điều này cho thấy kết quả có mức độ tin cậy cao trong việc phản ánh tỷ lệ giới tính thực tế của tổng thể.
Hơn nữa, do khoảng tin cậy tập trung xung quanh mốc 50%, có thể nhận thấy rằng phân bố giới tính trong tổng thể là tương đối cân bằng, không có sự chênh lệch đáng kể giữa nam và nữ.
Giả thuyết
prop.test(x=Gender, n=nrow(df_dt), p=0.5, correct=FALSE)
##
## 1-sample proportions test without continuity correction
##
## data: Gender out of nrow(df_dt), null probability 0.5
## X-squared = 5.6164, df = 1, p-value = 0.01779
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.5017287 0.5182531
## sample estimates:
## p
## 0.5099936
Kết quả kiểm định tỷ lệ mẫu đơn không hiệu chỉnh liên tục
Kết luận:
AnnualIncome <- sum(df_dt$AnnualIncome == "$10K - $30K")
conf_int_prop(AnnualIncome, nrow(df_dt), 0.95)
## Tỷ lệ mẫu Z tới hạn Sai số biên CI lower CI upper
## 0.219788036 1.959963985 0.006845091 0.212942946 0.226633127
Dựa trên kết quả phân tích, tỷ lệ mẫu có thu nhập trong khoảng $10k–$30k (mức thu nhập thấp nhất trong khảo sát) chiếm khoảng 22%. Với mức độ tin cậy 95%, ta có thể kết luận rằng tỷ lệ thu nhập trong khoảng này của toàn bộ quần thể nằm trong khoảng từ 21.29% đến 22.66%.
Khoảng tin cậy này tương đối hẹp, cho thấy cỡ mẫu được sử dụng là đủ lớn và tỷ lệ ước lượng có độ chính xác cao, với sai số biên chỉ khoảng 0.6%. Điều này chứng tỏ kết quả có mức độ tin cậy cao trong việc phản ánh tỷ lệ thu nhập thực tế của tổng thể.
Hơn nữa, do khoảng tin cậy tập trung quanh mức 22%, có thể nhận thấy rằng phân bố thu nhập trong khoảng $10k–$30k có sự chênh lệch đáng kể so với các mức thu nhập khác trong khảo sát.
Giả thuyết
prop.test(x=AnnualIncome, n=nrow(df_dt), p=0.2, correct=FALSE)
##
## 1-sample proportions test without continuity correction
##
## data: AnnualIncome out of nrow(df_dt), null probability 0.2
## X-squared = 34.406, df = 1, p-value = 4.472e-09
## alternative hypothesis: true p is not equal to 0.2
## 95 percent confidence interval:
## 0.2130200 0.2267092
## sample estimates:
## p
## 0.219788
Kết quả kiểm định tỷ lệ mẫu đơn không hiệu chỉnh liên tục
Kết luận:
ProductDepartment <- sum(df_dt$ProductDepartment == "Produce")
conf_int_prop(ProductDepartment, nrow(df_dt), 0.95)
## Tỷ lệ mẫu Z tới hạn Sai số biên CI lower CI upper
## 0.141830856 1.959963985 0.005766904 0.136063952 0.147597759
Dựa trên kết quả phân tích, tỷ lệ mẫu thuộc nhóm sản phẩm Produce (nhóm chiếm tỷ trọng cao nhất) chiếm khoảng 14%. Với mức độ tin cậy 95%, ta có thể kết luận rằng tỷ lệ nhóm sản phẩm Produce trong toàn bộ quần thể nằm trong khoảng từ 13.61% đến 14.76%.
Khoảng tin cậy này tương đối hẹp, cho thấy cỡ mẫu được sử dụng là đủ lớn và tỷ lệ ước lượng có độ chính xác cao, với sai số biên chỉ khoảng 0.58%. Điều này khẳng định kết quả có mức độ tin cậy cao trong việc phản ánh tỷ lệ thực tế của tổng thể.
Hơn nữa, do khoảng tin cậy tập trung quanh mức 14%, có thể nhận thấy rằng phân bố nhóm sản phẩm Produce có sự khác biệt đáng kể so với các nhóm sản phẩm khác trong khảo sát.
Giả thuyết
prop.test(x=ProductDepartment, n=nrow(df_dt), p=0.14, correct=FALSE)
##
## 1-sample proportions test without continuity correction
##
## data: ProductDepartment out of nrow(df_dt), null probability 0.14
## X-squared = 0.39141, df = 1, p-value = 0.5316
## alternative hypothesis: true p is not equal to 0.14
## 95 percent confidence interval:
## 0.1361617 0.1476956
## sample estimates:
## p
## 0.1418309
Kết quả kiểm định tỷ lệ mẫu đơn không hiệu chỉnh liên tục
Kết luận:
Với \(p-value\) = 0,516 > 0,05, không có đủ cơ sở để bác bỏ giả thuyết \(H_0\). Điều này cho thấy tỷ lệ thu nhập trong khoảng $10k–$30k trong tổng thể có thể coi là bằng đúng 14%. Mặc dù tỷ lệ mẫu quan sát được là 14,18%, sự chênh lệch này là không đáng kể về mặt thống kê. Nói cách khác, sự khác biệt giữa tỷ lệ quan sát và tỷ lệ giả định có thể chỉ là do yếu tố ngẫu nhiên trong quá trình chọn mẫu.
City <- sum(df_dt$City == "Salem")
conf_int_prop(City, nrow(df_dt), 0.95)
## Tỷ lệ mẫu Z tới hạn Sai số biên CI lower CI upper
## 0.098584537 1.959963985 0.004927626 0.093656910 0.103512163
Dựa trên kết quả phân tích, tỷ lệ mẫu thuộc thành phố Salem chiếm khoảng 9,96%. Với mức độ tin cậy 95%, ta có thể kết luận rằng tỷ lệ dân số của thành phố này trong toàn bộ quần thể nằm trong khoảng từ 9.37% đến 10.35%.
Khoảng tin cậy này tương đối hẹp, cho thấy cỡ mẫu được sử dụng là đủ lớn và tỷ lệ ước lượng có độ chính xác cao, với sai số biên chỉ khoảng 0.49%. Điều này khẳng định kết quả có mức độ tin cậy cao trong việc phản ánh tỷ lệ thực tế của tổng thể.
Hơn nữa, do khoảng tin cậy tập trung quanh mức 9,96%, có thể nhận thấy rằng tỷ lệ của thành phố Salem cao hơn đáng kể so với các địa phương khác trong khảo sát, cho thấy sự phân bố dân cư không đồng đều giữa các khu vực.
Giả thuyết
prop.test(x=City, n=nrow(df_dt), p=0.1, correct=FALSE)
##
## 1-sample proportions test without continuity correction
##
## data: City out of nrow(df_dt), null probability 0.1
## X-squared = 0.31297, df = 1, p-value = 0.5759
## alternative hypothesis: true p is not equal to 0.1
## 95 percent confidence interval:
## 0.09376602 0.10362236
## sample estimates:
## p
## 0.09858454
Kết quả kiểm định tỷ lệ mẫu đơn không hiệu chỉnh liên tục
Kết luận:
Với \(p-value\) = 0,5759 > 0,05, không có đủ cơ sở để bác bỏ giả thuyết \(H_0\). Điều này cho thấy tỷ lệ mua hàng tại thành phố Salem trong tổng thể có thể coi là bằng đúng 10%. Mặc dù tỷ lệ mẫu quan sát được là 9,96%, sự chênh lệch này là không đáng kể về mặt thống kê. Nói cách khác, sự khác biệt giữa tỷ lệ quan sát và tỷ lệ giả định có thể chỉ là do yếu tố ngẫu nhiên trong quá trình chọn mẫu.
Giả thuyết
# Hàm tính khoảng tin cậy một phía cho tỷ lệ mẫu
x <- table(df_dt$Country)
prop.test(c(x[["Canada"]],x[["Mexico"]]),c(sum(x),sum(x)),correct = TRUE)
##
## 2-sample test for equality of proportions with continuity correction
##
## data: c(x[["Canada"]], x[["Mexico"]]) out of c(sum(x), sum(x))
## X-squared = 2192.5, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
## -0.2130785 -0.1964812
## sample estimates:
## prop 1 prop 2
## 0.05754321 0.26232307
Kết quả kiểm định tỷ lệ mẫu đơn không hiệu chỉnh liên tục
Kết luận:
Với \(p-value\) < 2.2e-16 < 0,05, có đủ cơ sở để bác bỏ giả thuyết \(H_0\). Điều này cho thấy tỷ lệ mua hàng tại 2 quốc gia Canada và Mexico là khác nhau. Hay gọi là có sự chênh lệch đáng kể.
Cần thiết phải xem xét liệu giới tính có thực sự ảnh hưởng đến nhu cầu mua sắm các loại sản phẩm chính hay không, cũng như liệu có sự khác biệt đáng kể trong sự lựa chọn các nhóm sản phẩm giữa các giới tính hay không.
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.4.3
library(janitor) # Hỗ trợ làm sạch dữ liệu và tạo bảng Tần số chéo nhiều biến.
## Warning: package 'janitor' was built under R version 4.4.3
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
# Tạo bảng Tần số chéo và tính tỷ lệ phần trăm theo hàng (giới tính)
df_dt %>%
tabyl (Gender, ProductFamily,) %>% # Tạo bảng chéo Tần số, đếm Tần số
adorn_percentages("row") %>% # Tính tỷ lệ phần trăm theo hàng
adorn_pct_formatting(digits = 2) %>% # Định dạng phần trăm (ví dụ: 45.2%)
kable(
format = "html",
caption = "Bảng 4.1: Bảng tần suất (%) chéo giữa giới tính và danh mục sản phẩm chính",
align = "c"
) %>%
kable_styling(full_width = FALSE, position = "center",
bootstrap_options = c("striped", "hover")) # Làm đẹp bảng: kẻ sọc, hover
Gender | Drink | Food | Non-Consumable |
---|---|---|---|
F | 9.33% | 71.81% | 18.86% |
M | 8.43% | 72.64% | 18.93% |
Lưu ý: Kết quả phản ánh sự tương đồng trong hành vi mua sắm giữa các giới tính đối với các nhóm sản phẩm chính, đặc biệt là nhóm sản phẩm không tiêu hao, cho thấy mức độ ưu tiên tương tự nhau mức chênh lệch dưới 1%.
So sánh tỷ lệ phân phối sản phẩm giữa hai giới cho thấy nam giới có xu hướng ưa chuộng các danh mục như Food và Non-Consumable hơn so với nữ giới, thể hiện qua tỷ trọng tổng thể cao hơn ở các nhóm sản phẩm này.
# Tính Tần số và phần trăm theo ProductFamily và Gender
df_summary <- df_dt %>%
group_by(ProductFamily, Gender) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(ProductFamily) %>%
mutate(pct = n / sum(n) * 100)
# Vẽ biểu đồ với nhãn là số lượng và %
ggplot(df_summary, aes(x = ProductFamily, y = n, fill = Gender)) +
geom_bar(stat = "identity", position = position_dodge(0.9)) +
geom_text(aes(label = paste0(n, "\n(", sprintf("%.1f", pct), "%)")), # Hiển thị cả số lượng (n) và % (pct) trên cột
position = position_dodge(0.9),
vjust = 1, size = 3) +
labs(title = "Phân phối sản phẩm chính theo giới tính",
x = "Danh mục sản phẩm",
y = "Số lượng",
fill = "Giới tính") +
scale_fill_brewer(palette = "Set2") +
theme_minimal()
ggplot(df_summary, aes(x = ProductFamily, y = n, fill = Gender)) +
geom_bar(stat = "identity") +
labs(
title = "Phân phối sản phẩm chính theo giới tính",
x = "Danh mục sản phẩm",
y = "Số lượng",
fill = "Giới tính"
) +
scale_fill_brewer(palette = "Set2") +
theme_minimal()
Ghi chú:
Biểu đồ tiếp tục phản ánh rõ sự khác biệt trong hành vi tiêu dùng giữa các danh mục sản phẩm chính khi được phân tách theo giới tính. Cụ thể, danh mục Food vẫn duy trì mức chênh lệch đáng kể giữa hai giới, với tỷ lệ chênh lệch là 1,42% (tương ứng 145 đơn hàng). Điều này cho thấy đây là nhóm sản phẩm có sức mua cao và thể hiện rõ nét sự phân hóa trong hành vi tiêu dùng theo giới.
Ngược lại, danh mục Drink – nhóm có tỷ lệ mua sắm thấp nhất – thể hiện mức độ ưu tiên thấp hơn từ cả hai giới. Tuy nhiên, vẫn ghi nhận sự chênh lệch giới tính ở mức 7,04% (tương ứng 88 đơn hàng).
Nhìn chung, tổng số đơn hàng từ khách hàng nữ đều cao hơn so với nam giới ở cả ba danh mục sản phẩm chính, phản ánh xu hướng tiêu dùng chủ động và tích cực hơn từ phía nữ giới trong các nhóm hàng hóa được khảo sát
Giả thuyết
# Tạo bảng Tần số giữa Gender và ProductFamily
table_chisq <- table(df_dt$Gender, df_dt$ProductFamily)
# Thực hiện kiểm định Chi-squared
chi1 <- chisq.test(table_chisq)
# In kết quả kiểm định
print(chi1)
##
## Pearson's Chi-squared test
##
## data: table_chisq
## X-squared = 3.5185, df = 2, p-value = 0.1722
Kết quả kiểm định Chi-squared
Kết luận:
Với \(p-value\) = 0.1722
> 0.05, ta không có bằng chứng để bác bỏ giả thuyết \(H_0\).
Do đó, hai biến quan sát có không có mối liên hệ với nhau, nghĩa là 2
biến độc lập.
Cần thiết phải xem xét kỹ lưỡng liệu thu nhập có ảnh hưởng đáng kể đến việc sở hữu nhà của khách hàng hay không.
library(tidyr)
library(janitor) # Hỗ trợ làm sạch dữ liệu và tạo bảng Tần số chéo nhiều biến.
# Tạo bảng Tần số chéo và tính tỷ lệ phần trăm theo hàng (giới tính)
df_dt %>%
tabyl(Homeowner, AnnualIncome) %>% # Tạo bảng chéo Tần số, đếm Tần số
adorn_percentages("row") %>% # Tính tỷ lệ phần trăm theo từng hàng
adorn_pct_formatting(digits = 2) %>% # Định dạng phần trăm (ví dụ: 45.2%)
kable(
format = "html",
caption = "Bảng 4.2: Bảng tần suất (%) chéo thu nhập và việc sở hữu nhà",
align = "c"
) %>%
kable_styling(full_width = FALSE, position = "center",
bootstrap_options = c("striped", "hover")) # Làm đẹp bảng: kẻ sọc, hover
Homeowner | $10K - $30K | $110K - $130K | $130K - $150K | $150K + | $30K - $50K | $50K - $70K | $70K - $90K | $90K - $110K |
---|---|---|---|---|---|---|---|---|
N | 24.20% | 2.12% | 2.42% | 0.85% | 37.17% | 18.93% | 12.22% | 2.08% |
Y | 20.50% | 6.21% | 7.39% | 2.66% | 29.77% | 15.48% | 12.12% | 5.87% |
Lưu ý: Kết quả cho thấy hành vi mua sắm giữa nhóm khách hàng có và không có nhà ở có thể chịu ảnh hưởng bởi mức thu nhập. Phần lớn khách hàng không sở hữu nhà có thu nhập dao động trong khoảng $10k - $90k, với sự chênh lệch đáng kể so với nhóm có nhà – vốn chiếm phần lớn trong phân khúc khách hàng chính. Đáng chú ý, theo khảo sát, đa số khách hàng có thu nhập trên $90k hầu như sở hữu nhà và thể hiện sức mua cao hơn so với nhóm còn lại.
So sánh tỷ lệ phân phối sản phẩm giữa hai nhóm khách hàng này cho thấy sự chênh lệch rõ rệt ở các phân khúc thu nhập khác nhau.
# Tính Tần số và phần trăm theo ProductFamily và Gender
df_summary <- df_dt %>%
group_by(Homeowner, AnnualIncome) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(AnnualIncome) %>%
mutate(pct = n / sum(n) * 100)
# Vẽ biểu đồ với nhãn là số lượng và phần trăm theo nhóm thu nhập và tình trạng sở hữu nhà
ggplot(df_summary, aes(x = AnnualIncome, y = n, fill = Homeowner)) +
geom_bar(stat = "identity", position = position_dodge(0.9)) +
geom_text(aes(label = paste0(n, "\n(", sprintf("%.1f", pct), "%)")), # Hiển thị cả số lượng (n) và % (pct) trên cột
position = position_dodge(0.9),
vjust = 0.5, size = 3) +
labs(title = "Phân phối số đơn hàng theo thu nhập và tình trạng sở hữu nhà",
x = "Nhóm thu nhập hằng năm",
y = "Số lượng đơn hàng",
fill = "Tình trạng sở hữu nhà") +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
ggplot(df_summary, aes(x = AnnualIncome, y = n, fill = Homeowner)) +
geom_bar(stat = "identity") +
labs(title = "Phân phối số đơn hàng theo thu nhập và tình trạng sở hữu nhà",
x = "Nhóm thu nhập hằng năm",
y = "Số lượng đơn hàng",
fill = "Tình trạng sở hữu nhà") +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Ghi chú:
Biểu đồ tiếp tục thể hiện rõ sự khác biệt trong hành vi tiêu dùng giữa các nhóm thu nhập, khi được phân tách theo trạng thái sở hữu nhà. Cụ thể, trong nhóm thu nhập từ $30k–$50k, mức chênh lệch về sức mua giữa khách hàng có và chưa sở hữu nhà vẫn duy trì ở mức đáng kể, với tỷ lệ 9,3% (tương đương 427 đơn hàng).
Đáng chú ý, nhóm khách hàng có thu nhập trên $150k lại ghi nhận tỷ lệ mua hàng thấp nhất, với mức chênh lệch 64,83% (tương ứng 177 đơn hàng), cho thấy sự suy giảm rõ rệt trong nhu cầu mua sắm ở phân khúc thu nhập cao này.
Điều này cho thấy tổng số lượng đơn hàng từ nhóm khách hàng sở hữu nhà đều cao hơn so với nhóm chưa sở hữu nhà ở cả 9 nhóm thu nhập hằng năm được khảo sát. Kết quả phản ánh xu hướng tiêu dùng tích cực và ổn định hơn từ nhóm khách hàng có nhà, bất kể mức thu nhập tương ứng
Giả thuyết
# Tạo bảng Tần số giữa Gender và ProductFamily
table_chisq <- table(df_dt$AnnualIncome, df_dt$Homeowner)
# Thực hiện kiểm định Chi-squared
chi2 <- chisq.test(table_chisq)
# In kết quả kiểm định
print(chi2)
##
## Pearson's Chi-squared test
##
## data: table_chisq
## X-squared = 546.37, df = 7, p-value < 2.2e-16
Kết quả kiểm định Chi-squared
Kết luận:
Với \(p-value\) = 2.2e-16
< 0.05, ta có bằng chứng để bác bỏ giả thuyết \(H_0\), chấp nhận \(H_1\).
Điều này cho thấy giữa hai biến quan sát tồn tại mối liên hệ có ý nghĩa
thống kê, tức là chúng có sự liên kết đáng kể với nhau.
Việc phân tích thu nhập theo từng Bang/Tỉnh đến là cần thiết nhằm đánh giá xem yếu tố địa lý có ảnh hưởng đến nhu cầu mua sắm của khách hàng hay không. Đồng thời, điều này cũng giúp nhận diện rõ liệu có sự khác biệt đáng kể nào trong cơ cấu thu nhập giữa các địa phương, cũng như xác định Bang/Tỉnh nào đang thực sự chiếm ưu thế về mức thu nhập – từ đó gợi ý tiềm năng tiêu dùng vượt trội
# Tạo bảng Tần số chéo và tính tỷ lệ phần trăm theo hàng (giới tính)
df_dt %>%
tabyl (StateorProvince, AnnualIncome) %>% # Tạo bảng chéo Tần số, đếm Tần số
adorn_percentages("row") %>% # Tính tỷ lệ phần trăm theo hàng
adorn_pct_formatting(digits = 2) %>% # Định dạng phần trăm (ví dụ: 45.2%)
kable(
format = "html",
caption = "Bảng 4.3: Bảng tần suất (%) chéo giữa thu nhập và bang/tỉnh",
align = "c"
) %>%
kable_styling(full_width = FALSE, position = "center",
bootstrap_options = c("striped", "hover")) # Làm đẹp bảng: kẻ sọc, hover
StateorProvince | $10K - $30K | $110K - $130K | $130K - $150K | $150K + | $30K - $50K | $50K - $70K | $70K - $90K | $90K - $110K |
---|---|---|---|---|---|---|---|---|
BC | 21.26% | 6.06% | 5.56% | 1.98% | 36.59% | 15.57% | 9.89% | 3.09% |
CA | 21.92% | 4.76% | 4.54% | 2.34% | 32.49% | 17.97% | 11.38% | 4.61% |
DF | 21.72% | 4.05% | 7.36% | 1.35% | 35.09% | 15.95% | 10.80% | 3.68% |
Guerrero | 31.85% | 3.92% | 3.92% | 2.61% | 27.15% | 15.67% | 10.97% | 3.92% |
Jalisco | 38.67% | 2.67% | 4.00% | 0.00% | 22.67% | 17.33% | 12.00% | 2.67% |
OR | 22.72% | 4.11% | 5.84% | 1.19% | 32.01% | 16.71% | 12.11% | 5.31% |
Veracruz | 18.32% | 7.33% | 7.54% | 1.08% | 30.60% | 22.41% | 9.91% | 2.80% |
WA | 22.01% | 4.23% | 5.45% | 2.43% | 32.89% | 16.82% | 12.28% | 3.90% |
Yucatan | 17.28% | 3.52% | 5.50% | 2.29% | 35.17% | 13.00% | 16.06% | 7.19% |
Zacatecas | 21.13% | 5.47% | 4.70% | 1.08% | 31.77% | 16.58% | 14.88% | 4.39% |
Lưu ý: Kết quả phân tích cho thấy hành vi mua sắm của khách hàng tại các Bang/Tỉnh có thể chịu ảnh hưởng đáng kể bởi mức thu nhập. Phần lớn khách hàng tập trung trong nhóm thu nhập từ $10k đến $90k, trong đó khoảng $30k–$50k thường chiếm tỷ trọng cao nhất. Tuy nhiên, có hai ngoại lệ đáng chú ý là các thành phố Guerrero và Jalisco, nơi nhóm khách hàng có thu nhập $10k–$30k lại chiếm ưu thế vượt trội.
So sánh tỷ lệ phân phối sản phẩm giữa các nhóm thu nhập và khu vực địa lý cũng cho thấy sự chênh lệch đáng kể.
ggplot(df_dt, aes(x = StateorProvince, fill = AnnualIncome)) +
geom_bar(position = position_dodge(width = 0.8)) +
geom_text(stat = "count",
aes(label = after_stat(count)),
position = position_dodge(width = 0.8),
vjust = -0.3, size = 2.5, check_overlap = TRUE) +
labs(title = "Phân phối đơn hàng theo thu nhập và bang/tỉnh",
x = "Bang/Tỉnh", y = "Số đơn hàng", fill = "Thu nhập") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
ggplot(df_dt, aes(x = StateorProvince, fill = AnnualIncome)) +
geom_bar() +
labs(title = "Phân phối đơn hàng theo thu nhập và bang/tỉnh",
x = "Bang/Tỉnh", y = "Số đơn hàng", fill = "Thu nhập") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
Ghi chú:
Biểu đồ tiếp tục làm rõ sự khác biệt trong hành vi tiêu dùng giữa các nhóm thu nhập, đặc biệt khi được phân tích chi tiết theo từng bang/tỉnh. Trong đó, bang WA (Washington) nổi bật với tổng số lượng đơn hàng cao nhất, theo sau là CA (California) và OR (Oregon). Khoảng cách giữa nhóm dẫn đầu và các bang còn lại là tương đối lớn, cho thấy sự tập trung tiêu dùng đáng kể tại một số khu vực nhất định..
Ngược lại, các thành phố như Jalisco và Guerrero ghi nhận tỷ lệ đơn hàng thấp nhất, phản ánh mức thu nhập phổ biến tại đây chủ yếu nằm trong khoảng $10k–$30k. Điều này cho thấy nhu cầu tiêu dùng từ các phân khúc thu nhập cao tại hai khu vực này đang ở mức rất hạn chế, có thể bắt nguồn từ đặc điểm kinh tế - xã hội hoặc sự khác biệt trong thói quen chi tiêu của cư dân địa phương.
Từ kết quả này, có thể thấy rằng nhóm khách hàng tại bang WA cùng với các nhóm thu nhập trong khoảng $10k – $90k là đối tượng đóng góp chính vào tổng doanh số. Do đó, các chiến lược định vị sản phẩm, đặc biệt là về giá bán, nên ưu tiên nhắm tới phân khúc thu nhập trung bình này
Giả thuyết
# Tạo bảng Tần số giữa Gender và ProductFamily
table_chisq <- table(df_dt$AnnualIncome, df_dt$StateorProvince)
# Thực hiện kiểm định Chi-squared
chi3 <- chisq.test(table_chisq)
## Warning in stats::chisq.test(x, y, ...): Chi-squared approximation may be
## incorrect
# In kết quả kiểm định
print(chi3)
##
## Pearson's Chi-squared test
##
## data: table_chisq
## X-squared = 181.72, df = 63, p-value = 1.893e-13
Kết quả kiểm định Chi-squared
Kết luận:
Với \(p-value\) = 2.2e-16
< 0.05, ta có bằng chứng để bác bỏ giả thuyết \(H_0\), chấp nhận \(H_1\).
Điều này cho thấy giữa hai biến quan sát tồn tại mối liên hệ có ý nghĩa
thống kê, tức là chúng có sự liên kết đáng kể với nhau.
Giới tính: Tỷ lệ nam và nữ trong mẫu không có sự khác biệt đáng kể. Ước lượng tỷ lệ nữ dao động quanh mức 50%, phản ánh sự phân bổ gần như cân bằng giữa hai giới.
Tình trạng sở hữu nhà: Khách hàng sở hữu nhà chiếm tỷ lệ cao hơn đáng kể so với nhóm chưa sở hữu nhà, cho thấy nhóm này chiếm ưu thế trong dữ liệu.
Tình trạng hôn nhân: Nhóm độc thân chiếm tỷ lệ cao hơn, nhưng sự chênh lệch giữa các nhóm hôn nhân không lớn, cho thấy sự phân bố tương đối đồng đều.
Thu nhập hàng năm: Phần lớn khách hàng tập trung trong nhóm thu nhập từ $10k-$90k, nổi bật nhất là khoảng thu nhập $30k-$50k với ước lượng tỷ lệ dao động chiếm gần 20%. Tỷ lệ khách hàng giảm dần khi thu nhập tăng cao, phản ánh phân bố chủ yếu thuộc tầng lớp trung lưu.
Quốc gia: Khách hàng đến từ Hoa Kỳ (USA) chiếm hơn một nửa tổng số đơn hàng, cho thấy đây là thị trường chủ lực và quan trọng nhất.
Thành phố: Thành phố Salem ghi nhận số lượng đơn hàng cao nhất, chiếm khoảng 10%, tương thích với dự báo từ kiểm định tỷ lệ.
Phân khúc sản phẩm chính: Nhóm sản phẩm Food là phân khúc được ưa chuộng nhất, chiếm trên 50% tổng số đơn hàng, phản ánh rõ xu hướng tiêu dùng tập trung vào thực phẩm.
Bộ phận sản phẩm phụ: Trong các bộ phận sản phẩm, nhóm Produce dẫn đầu với tỷ trọng khoảng 14%, phù hợp với ước lượng từ kiểm định tỷ lệ.
Danh mục cụ thể: Sản phẩm thuộc nhóm Vegetables được lựa chọn nhiều hơn hẳn so với các danh mục khác, thể hiện ưu tiên rõ ràng trong lựa chọn sản phẩm.
Mối quan hệ giữa các biến: Không phát hiện mối liên hệ đáng kể giữa giới tính và nhóm sản phẩm chính, cho phép phân tích hai yếu tố này một cách độc lập. Tuy nhiên, thu nhập hàng năm lại có mối liên hệ chặt chẽ với thành phố cư trú và tình trạng sở hữu nhà, cho thấy những yếu tố này ảnh hưởng đáng kể đến hành vi tiêu dùng và khả năng chi tiêu của khách hàng.
Nghiên cứu chủ yếu tập trung vào các biến định tính để phân tích hành vi tiêu dùng, chưa khai thác sâu các biến định lượng quan trọng như doanh thu (Revenue) và số lượng sản phẩm bán ra (UnitsSold), vốn có thể ảnh hưởng đáng kể đến phân nhóm khách hàng và lựa chọn sản phẩm. Ngoài ra, biến đặc điểm gia đình như số lượng con cái (Children) cũng chưa được xem xét, trong khi đây là yếu tố có thể tác động trực tiếp đến khả năng mua hàng của hộ gia đình.
Phạm vi nghiên cứu giới hạn ở 3 quốc gia, tập trung chủ yếu vào thị trường sử dụng đồng USD, bỏ qua sự đa dạng của các thị trường khác với đặc điểm kinh tế và thu nhập khác biệt. Về phương pháp, các kiểm định dựa trên giả định mẫu đủ lớn và phân nhóm đồng đều. Khi mẫu nhỏ hoặc phân nhóm không đồng đều, kết quả có thể không chính xác, dẫn đến cảnh báo như “Chi-squared approximation may be incorrect”. Ngoài ra, các mô hình hiện tại chưa khai thác các tương tác phức tạp giữa các biến, hạn chế khả năng giải thích hành vi tiêu dùng thực tế.
Mở rộng nghiên cứu bằng cách bổ sung các biến định lượng có sẵn như doanh thu (Revenue), số lượng sản phẩm bán ra (UnitsSold) và số lượng con cái (Children), nhằm phân tích sâu sắc hơn ảnh hưởng đa chiều của các yếu tố nội lực.
Bổ sung đặc điểm gia đình như số thành viên trong hộ, đồng thời tích hợp các biến nhân khẩu học bổ sung như tuổi, trình độ học vấn, nghề nghiệp, tình trạng việc làm, cùng với các biến kinh tế vĩ mô như tỷ lệ thất nghiệp, lạm phát, tốc độ tăng trưởng GDP của khu vực nghiên cứu, nhằm làm rõ hơn tác động của các yếu tố xã hội và kinh tế đến khả năng chi tiêu.
Mở rộng phạm vi nghiên cứu sang các quốc gia và thị trường đa dạng hơn, nhằm tăng tính tổng quát của kết quả và so sánh sự khác biệt về hành vi tiêu dùng dựa trên đặc điểm kinh tế và văn hóa riêng biệt.
Áp dụng các phương pháp kiểm định phù hợp với đặc điểm mẫu nhỏ và cấu trúc dữ liệu phức tạp, như kiểm định phi tham số hoặc mô hình hồi quy đa biến với biến phân loại, nhằm nâng cao độ chính xác và độ tin cậy của phân tích.
Khai thác các mô hình tương tác và phân tích đa chiều để hiểu rõ hơn các mối quan hệ phức tạp giữa các biến định tính và định lượng trong hành vi tiêu dùng, từ đó đưa ra những kết luận sâu sắc và toàn diện hơn.