# Đọc dữ liệu
data <- read.csv("C:/Users/Welcome !/Downloads/Supermarket Transactions.csv")
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 ...
head(data)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 1 1 2007-12-18 7223 F S Y 2
## 2 2 2007-12-20 7841 M M Y 5
## 3 3 2007-12-21 8374 F M N 2
## 4 4 2007-12-21 9619 M M Y 3
## 5 5 2007-12-22 1900 F S Y 3
## 6 6 2007-12-22 6696 F M Y 3
## AnnualIncome City StateorProvince Country ProductFamily
## 1 $30K - $50K Los Angeles CA USA Food
## 2 $70K - $90K Los Angeles CA USA Food
## 3 $50K - $70K Bremerton WA USA Food
## 4 $30K - $50K Portland OR USA Food
## 5 $130K - $150K Beverly Hills CA USA Drink
## 6 $10K - $30K Beverly Hills CA USA Food
## ProductDepartment ProductCategory UnitsSold Revenue
## 1 Snack Foods Snack Foods 5 27.38
## 2 Produce Vegetables 5 14.90
## 3 Snack Foods Snack Foods 3 5.52
## 4 Snacks Candy 4 4.44
## 5 Beverages Carbonated Beverages 4 14.00
## 6 Deli Side Dishes 3 4.37
tail(data)
## X PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
## 14054 14054 2009-12-29 2032 F M N 3
## 14055 14055 2009-12-29 9102 F M Y 2
## 14056 14056 2009-12-29 4822 F M Y 3
## 14057 14057 2009-12-31 250 M S Y 1
## 14058 14058 2009-12-31 6153 F S N 4
## 14059 14059 2009-12-31 3656 M S N 3
## AnnualIncome City StateorProvince Country ProductFamily
## 14054 $10K - $30K Yakima WA USA Non-Consumable
## 14055 $10K - $30K Bremerton WA USA Food
## 14056 $10K - $30K Walla Walla WA USA Food
## 14057 $30K - $50K Portland OR USA Drink
## 14058 $50K - $70K Spokane WA USA Drink
## 14059 $50K - $70K Portland OR USA Non-Consumable
## ProductDepartment ProductCategory UnitsSold Revenue
## 14054 Household Paper Products 5 14.50
## 14055 Baking Goods Baking Goods 3 9.64
## 14056 Frozen Foods Vegetables 3 7.45
## 14057 Beverages Pure Juice Beverages 4 3.24
## 14058 Dairy Dairy 2 4.00
## 14059 Household Electrical 5 25.53
any(is.na(data))
## [1] FALSE
Kết quả trả về FALSE nghĩa là không có bất kỳ giá trị thiếu (NA) nào trong toàn bộ dataframe
data[] <- lapply(data, function(x) if (is.character(x)) as.factor(x) else x)
qual_data <- data[sapply(data, is.factor)]
Đoạn code trên dùng để tự động chuyển tất cả các cột có kiểu dữ liệu character trong dataframe data sang kiểu factor. Việc này rất quan trọng vì các biến dạng chữ thường biểu thị cho dữ liệu phân loại, và khi được chuyển thành factor, R sẽ hiểu đúng bản chất của chúng như các nhóm hoặc mức phân loại riêng biệt. Điều này giúp các mô hình thống kê và phân tích sau đó xử lý chính xác hơn các biến này, đồng thời hỗ trợ việc phân tích và trực quan hóa dữ liệu dễ dàng hơn.
# Tạo bảng tần suất cho biến Gender
freq_tableGender <- table(qual_data$Gender)
# Tính tỷ lệ phần trăm
percent_tableGender <- prop.table(freq_tableGender) * 100
## Tần suất các quan sát của biến Gender :
##
## F M
## 7170 6889
## Tỷ lệ phần trăm các quan sát của biến ProductDepartmentu:
##
## F M
## 51 49
# Biểu đồ cột
barplot(freq_tableGender,
col = c("darkblue", "beige"), # đổi thành 2 màu cho 2 cột
main = "Biểu đồ cột thể hiệu giới tính của số người trong dữ liệu nghiên cứu",
ylab = "Tần suất",
xlab = "Giới Tính ")
legend("topright",
legend = c("Nữ ", "Nam"), # chú thích cho 2 cột
fill = c("darkblue", "beige"))
Nhận xét :Trong tổng số người tham gia, nữ giới (F) chiếm 7170 người, trong khi nam giới (M) chiếm 6889 người. Mặc dù sự chênh lệch không quá lớn, nhưng số lượng nữ giới vẫn nhỉnh hơn nam giới trong tập dữ liệu này. Biểu đồ cho thấy sự phân bố giới tính tương đối cân đối, tuy nhiên nữ giới chiếm tỷ lệ cao hơn một chút.
# Tạo bảng tần suất
freq_table <- table(qual_data$MaritalStatus)
# Tính tỷ lệ phần trăm
percent_table <- prop.table(freq_table) * 100
## Tần suất các quan sát của biến MaritalStatus :
##
## M S
## 6866 7193
## Tỷ lệ phần trăm các quan sát của biến MaritalStatus:
##
## M S
## 48.84 51.16
# Biểu đồ cột
colors <- c("skyblue", "darkblue", "darkblue")
barplot(freq_table,
col = colors,
main = "Biểu đồ cột thể hiện tình trạng hôn nhân trong khảo sát",
ylab = "Tần suất",
xlab = "Tình trạng hôn nhân")
legend("topright", legend = names(freq_table), fill = colors, cex = 0.8)
Nhận xét : Số lượng người độc thân (S) cao hơn so với số lượng người đã kết hôn (M).Cụ thể, tần suất người độc thân gần 7193, trong khi người đã kết hôn khoảng 6866 .Chênh lệch không lớn: mặc dù có sự khác biệt, nhưng khoảng cách tần suất giữa hai nhóm không quá lớn, cho thấy phân bố tình trạng hôn nhân trong dữ liệu nghiên cứu là khá cân đối giữa người đã kết hôn và độc thân.
# Tạo bảng tần suất cho biến Homeowner
freq_tableHomeowner <- table(qual_data$Homeowner)
# Tính tỷ lệ phần trăm
percent_tableHomeowner <- prop.table(freq_tableHomeowner) * 100
## Tần suất các quan sát của biến Homeowners :
##
## N Y
## 5615 8444
## Tỷ lệ phần trăm các quan sát của biến Homeowneru:
##
## N Y
## 39.94 60.06
# Biểu đồ cột
barplot(freq_tableHomeowner,
col = c("brown", "beige"), # đổi thành 2 màu cho 2 cột
main = "Biểu đồ cột thể hiện số người sỡ hữu nhà trong dữ liệu nghiên cứu",
ylab = "Tần suất",
xlab = "Số người sỡ hữu nhà ")
legend("topright",
legend = c("Có nhà", "Không có nhà"), # chú thích cho 2 cột
fill = c("brown", "beige"))
Nhận xét :Dựa trên biểu đồ cột thể hiện số người sở hữu nhà trong dữ liệu nghiên cứu, có thể thấy rằng số lượng người có nhà (Y) chiếm tỷ lệ cao hơn rõ rệt so với số người không có nhà (N). Cụ thể, tần suất của nhóm có nhà vào khoảng 8444, trong khi nhóm không có nhà chỉ khoảng 5615. Điều này cho thấy trong mẫu dữ liệu nghiên cứu, đa số người tham gia có sở hữu nhà ở. Sự chênh lệch này khá rõ ràng và có thể phản ánh mức độ ổn định về mặt kinh tế – xã hội của nhóm người được khảo sát. Đây cũng có thể là một yếu tố quan trọng để phân tích sâu hơn khi xem xét mối liên hệ với các biến khác như tình trạng hôn nhân, thu nhập hoặc khả năng vay vốn.
# Tạo bảng tần suất cho biến AnnualIncome
freq_tableAnnualIncome <- table(qual_data$AnnualIncome)
# Tính tỷ lệ phần trăm
percent_tableAnnualIncome <- prop.table(freq_tableAnnualIncome) * 100
## Tần suất các quan sát của biến AnnualIncome :
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 3090 643 760 273 4601
## $50K - $70K $70K - $90K $90K - $110K
## 2370 1709 613
## Tỷ lệ phần trăm các quan sát của biến AnnualIncomeu:
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 21.98 4.57 5.41 1.94 32.73
## $50K - $70K $70K - $90K $90K - $110K
## 16.86 12.16 4.36
# Biểu đồ cột với nhãn xoay dọc
barplot(freq_tableAnnualIncome,
col = rainbow(length(freq_tableAnnualIncome)),
main = "Biểu đồ cột thể hiện phân bố mức thu nhập hằng năm",
ylab = "Tần suất",
xlab = "",
las = 2, # Xoay nhãn trục x theo chiều dọc
cex.names = 0.8) # Thu nhỏ chữ nếu quá dài
# Thêm chú thích
legend("topright",
legend = names(freq_tableAnnualIncome),
fill = rainbow(length(freq_tableAnnualIncome)))
Nhận xét : Biểu đồ phân bố tần suất thu nhập hàng năm cho thấy một cái nhìn rõ nét về cơ cấu thu nhập trong bộ dữ liệu nghiên cứu. Nổi bật nhất là nhóm thu nhập từ $30K – $50K, với 4.601 cá nhân, chiếm tỷ lệ cao nhất và thể hiện đây là mức thu nhập phổ biến nhất trong mẫu khảo sát. Điều này cho thấy phần lớn đối tượng nghiên cứu tập trung ở phân khúc thu nhập trung bình thấp. Kế đó, nhóm $10K – $30K cũng chiếm một phần đáng kể với 3.090 người, củng cố nhận định về sự tập trung của phần lớn cá nhân ở các nhóm thu nhập dưới mức trung bình. Ngược lại, các nhóm thu nhập cao hơn như $110K – $130K, $130K – $150K và đặc biệt là trên $150K chỉ ghi nhận tần suất rất thấp (lần lượt 643, 760 và 273 người). Sự chênh lệch rõ rệt này chỉ ra rằng, trong bộ dữ liệu, các mức thu nhập cao hơn là hiếm gặp và không đại diện cho phần lớn dân số nghiên cứu. Xu hướng chung của biểu đồ là sự phân bố lệch trái, với mật độ tần suất giảm dần khi mức thu nhập tăng lên, phản ánh đặc điểm thu nhập phổ biến thấp trong tập dữ liệu này.
# Tạo bảng tần suất cho biến City
freq_tableCity <- table(qual_data$City)
# Tính tỷ lệ phần trăm
percent_tableCity <- prop.table(freq_tableCity) * 100
## Tần suất các quan sát của biến 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
## Tỷ lệ phần trăm các quan sát của biến Cityu:
##
## Acapulco Bellingham Beverly Hills Bremerton Camacho
## 2.72 1.02 5.77 5.93 3.22
## Guadalajara Hidalgo Los Angeles Merida Mexico City
## 0.53 6.01 6.59 4.65 1.38
## Orizaba Portland Salem San Andres San Diego
## 3.30 6.23 9.86 4.42 6.16
## San Francisco Seattle Spokane Tacoma Vancouver
## 0.92 6.56 6.22 8.94 4.50
## Victoria Walla Walla Yakima
## 1.25 1.14 2.67
# Tên các thành phố và số lượng
cities <- names(freq_tableCity)
n <- length(freq_tableCity)
# Palette màu pastel tươi sáng, dễ nhìn, đủ phân biệt nhiều thành phố
colors <- c("#FF6F61", "#6B5B95", "#88B04B", "#F7CAC9", "#92A8D1",
"#955251", "#B565A7", "#009B77", "#DD4124", "#45B8AC")
colors <- rep(colors, length.out = n)
# Vẽ biểu đồ cột, ẩn tên mặc định trên trục X
bp <- barplot(freq_tableCity,
col = colors,
main = "Biểu đồ cột thể hiện tần suất phân bổ các thành phố",
ylab = "Tần suất",
xlab = "Các thành phố",
names.arg = rep("", n), # Ẩn tên mặc định
ylim = c(0, max(freq_tableCity) * 1.3),
las = 2) # Chữ nghiêng đứng (dọc) để dễ đọc
# Thêm chữ tên thành phố ở dưới trục X, đẩy xuống thấp hơn trục, nghiêng 45 độ
text(x = bp,
y = par("usr")[3] - 0.05 * max(freq_tableCity), # đẩy chữ xuống dưới trục
labels = cities,
srt = 45, # xoay nghiêng 45 độ
adj = 1,
xpd = TRUE,
cex = 0.7)
# Thêm bảng chú thích (legend) ở góc trên bên phải, đẩy lên cao hơn 5%
legend("topright",
legend = cities,
fill = colors,
border = "black",
title = "Thành phố",
cex = 0.7,
ncol = 2,
bty = "n",
inset = c(0, 0.08))
Nhận xét Dựa vào biểu đồ cột thể hiện tần suất phân bố người dân theo thành phố trong bộ dữ liệu, ta có thể nhận xét như sau: Các thành phố được khảo sát có mức độ dân cư phân bố khá đa dạng, tuy nhiên có sự chênh lệch rõ rệt về số lượng người sinh sống giữa các thành phố. Trong đó, thành phố Salem là nơi có số người sinh sống cao nhất, với tần suất lên đến 1386, nổi bật hơn hẳn so với các thành phố còn lại. Tiếp theo là Tacoma (1257) và Los Angeles (926) cũng có số người sinh sống khá cao. Một số thành phố khác như Portland (876), San Diego (866), Seattle (922), và Hidalgo (845) cũng có mức tần suất tương đối cao, thể hiện đây là những nơi tập trung dân cư đáng kể trong bộ dữ liệu. Ngược lại, một số thành phố có tần suất rất thấp, điển hình như Guadalajara (75), San Francisco (130), và Bellingham (143). Điều này cho thấy số lượng người sinh sống ở các thành phố này trong bộ dữ liệu là rất hạn chế. Tóm lại, Salem là thành phố nổi bật nhất với số người sinh sống cao nhất, phản ánh vai trò có thể quan trọng về kinh tế hoặc xã hội của thành phố này trong phạm vi nghiên cứu.
# Tạo bảng tần suất cho biến StateorProvince
freq_tableStateorProvince <- table(qual_data$StateorProvince)
# Tính tỷ lệ phần trăm
percent_tableStateorProvince <- prop.table(freq_tableStateorProvince) * 100
## Tần suất các quan sát của biến StateorProvince :
##
## 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
## Tỷ lệ phần trăm các quan sát của biếnStateorProvince:
##
## Acapulco Bellingham Beverly Hills Bremerton Camacho
## 2.72 1.02 5.77 5.93 3.22
## Guadalajara Hidalgo Los Angeles Merida Mexico City
## 0.53 6.01 6.59 4.65 1.38
## Orizaba Portland Salem San Andres San Diego
## 3.30 6.23 9.86 4.42 6.16
## San Francisco Seattle Spokane Tacoma Vancouver
## 0.92 6.56 6.22 8.94 4.50
## Victoria Walla Walla Yakima
## 1.25 1.14 2.67
# Tên các tỉnh/tiểu bang và số lượng
states <- names(freq_tableStateorProvince)
n <- length(freq_tableStateorProvince)
# Palette màu pastel tươi sáng, đủ phân biệt nhiều tỉnh/tiểu bang
colors <- c("#FF6F61", "#6B5B95", "#88B04B", "#F7CAC9", "#92A8D1",
"#955251", "#B565A7", "#009B77", "#DD4124", "#45B8AC")
colors <- rep(colors, length.out = n)
# Vẽ biểu đồ cột, ẩn tên mặc định trên trục X
bp <- barplot(freq_tableStateorProvince,
col = colors,
main = "Biểu đồ cột thể hiện Phân phối tần suất theo tiểu bang ",
ylab = "Tần suất",
xlab = "Các tỉnh hay tiểu bang",
names.arg = rep("", n), # Ẩn tên mặc định
ylim = c(0, max(freq_tableStateorProvince) * 1.3),
las = 2) # Chữ nghiêng đứng (dọc) để dễ đọc
# Thêm chữ tên tỉnh/tiểu bang ở dưới trục X, đẩy xuống thấp hơn trục, nghiêng 45 độ
text(x = bp,
y = par("usr")[3] - 0.05 * max(freq_tableStateorProvince), # đẩy chữ xuống dưới trục
labels = states,
srt = 45, # xoay nghiêng 45 độ
adj = 1,
xpd = TRUE,
cex = 0.7)
# Thêm bảng chú thích (legend) ở góc trên bên phải, đẩy lên cao 20%
legend("topright",
legend = states,
fill = colors,
border = "black",
title = "Tỉnh/TB",
cex = 0.7,
ncol = 2,
bty = "n",
inset = c(0, 0.001)) # Đẩy lên cao 20%
Nhận xét Nổi bật nhất là Salem, với tần suất cao vượt trội ở mức 1386, cho thấy đây là địa điểm có số lượng quan sát lớn nhất trong tập dữ liệu. Tiếp theo là Tacoma (1257) và Los Angeles (926), cùng với Seattle (922) và Portland (876), San Diego (866) và Spokane (875) cho thấy đây là những địa điểm có hoạt động hoặc sự hiện diện đáng kể. Ngược lại, một số địa điểm có tần suất rất thấp như Guadalajara (75), San Francisco (130), Bellingham (143), Walla Walla (160) và Victoria (176), cùng với Mexico City (194), phản ánh sự tập trung dữ liệu kém ở các khu vực này. Sự chênh lệch rõ rệt giữa các địa điểm có tần suất rất cao và rất thấp chỉ ra rằng dữ liệu không phân bố đồng đều, mà có xu hướng tập trung mạnh mẽ vào một số khu vực nhất định. Điều này gợi mở nhu cầu phân tích sâu hơn về các yếu tố địa lý, kinh tế-xã hội hoặc các đặc điểm riêng của từng địa điểm đã góp phần tạo nên sự phân bổ không đồng đều này.
# Tạo bảng tần suất cho biến ProductFamily
freq_tableProductFamily <- table(qual_data$ProductFamily)
# Tính tỷ lệ phần trăm
percent_tableProductFamily <- prop.table(freq_tableProductFamily) * 100
## Tần suất các quan sát của biến ProductFamily :
##
## Drink Food Non-Consumable
## 1250 10153 2656
## Tỷ lệ phần trăm các quan sát của biến ProductFamily:
##
## Drink Food Non-Consumable
## 8.89 72.22 18.89
products <- names(freq_tableProductFamily)
colors <- c("#FF7F50", "#6A5ACD", "#3CB371") # 3 màu dễ phân biệt
bp <- barplot(freq_tableProductFamily,
col = colors,
main = "Biểu đồ tần suất theo nhóm sản phẩm",
ylab = "Tần suất",
xlab = "Nhóm sản phẩm",
names.arg = products,
ylim = c(0, max(freq_tableProductFamily)*1.2))
legend("topright",
legend = products,
fill = colors,
border = "black",
title = "Nhóm sản phẩm",
cex = 0.8,
bty = "n")
Nhận xét Biểu đồ tần suất các quan sát theo biến ProductFamily cho thấy sự phân bố không đồng đều giữa các nhóm sản phẩm. Nhóm Food chiếm ưu thế với 10.153 quan sát, chiếm phần lớn dữ liệu, trong khi nhóm Non-Consumable có 2.656 quan sát và nhóm Drink thấp nhất với 1.250 quan sát. Sự chênh lệch đáng kể này phản ánh mức độ phổ biến và tần suất xuất hiện khác nhau giữa các nhóm sản phẩm trong tập dữ liệu.Khuyến nghị rằng khi phân tích hoặc xây dựng mô hình dựa trên dữ liệu này, cần lưu ý đến sự mất cân bằng trong số lượng quan sát giữa các nhóm để tránh hiện tượng thiên lệch kết quả. Có thể áp dụng các phương pháp cân bằng dữ liệu như kỹ thuật lấy mẫu lại (resampling), hoặc sử dụng trọng số trong mô hình để đảm bảo tính đại diện cho các nhóm có số lượng quan sát thấp hơn. Ngoài ra, việc phân tích riêng biệt từng nhóm cũng có thể giúp khai thác sâu hơn các đặc điểm riêng biệt và đưa ra kết luận chính xác hơn về hành vi tiêu dùng hoặc đặc tính của từng nhóm sản phẩm.
# Tạo bảng tần suất cho biến ProductDepartment
freq_tableProductDepartment <- table(qual_data$ProductDepartment)
# Tính tỷ lệ phần trăm
percent_tableProductDepartment <- prop.table(freq_tableProductDepartment) * 100
## Tần suất các quan sát của biến 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
## Tỷ lệ phần trăm các quan sát của biến ProductDepartmentu:
##
## Alcoholic Beverages Baked Goods Baking Goods Beverages
## 2.53 3.02 7.63 4.84
## Breakfast Foods Canned Foods Canned Products Carousel
## 1.34 6.95 0.78 0.42
## Checkout Dairy Deli Eggs
## 0.58 6.42 4.97 1.41
## Frozen Foods Health and Hygiene Household Meat
## 9.83 6.35 10.10 0.63
## Periodicals Produce Seafood Snack Foods
## 1.44 14.18 0.73 11.38
## Snacks Starchy Foods
## 2.50 1.97
library(RColorBrewer)
departments <- names(freq_tableProductDepartment)
n <- length(freq_tableProductDepartment)
# Lấy bảng màu "Set3" (có tối đa 12 màu pastel khác biệt, thay đổi nếu nhiều hơn 12)
if (n <= 12) {
colors <- brewer.pal(n, "Set3")
} else {
# Nếu nhiều hơn 12, tạo màu ngẫu nhiên rõ ràng
set.seed(123)
colors <- grDevices::rainbow(n)
}
bp <- barplot(freq_tableProductDepartment,
col = colors,
main = "Biểu đồ cột Tần suất quan sát theo phòng ban sản phẩm",
ylab = "Tần suất",
xlab = "",
names.arg = rep("", n),
ylim = c(0, max(freq_tableProductDepartment)*1.3),
las = 2)
text(x = bp,
y = par("usr")[3] - 0.05 * max(freq_tableProductDepartment),
labels = departments,
srt = 45,
adj = 1,
xpd = TRUE,
cex = 0.8)
legend("topright",
legend = departments,
fill = colors,
border = "black",
title = "ProductDepartment",
cex = 0.5,
bty = "n",
inset = c(0, -0.01))
Nhận xét Biểu đồ cho thấy sự phân bố không đồng đều về tần suất các quan sát giữa các phòng ban sản phẩm. Trong đó, Produce (Rau quả) có số lượng quan sát cao nhất với 1.994 lần, tiếp theo là Snack Foods (Đồ ăn vặt) với 1.600 quan sát và Household (Đồ gia dụng) với 1.420 quan sát. Các nhóm như Frozen Foods và Baking Goods cũng có số lượng khá cao, lần lượt là 1.382 và 1.072.Ngược lại, một số phòng ban có tần suất thấp hơn đáng kể, tiêu biểu như Carousel chỉ có 59 quan sát, Meat (Thịt) với 89, và Checkout với 82. Những sự chênh lệch này cho thấy mức độ phổ biến và trọng tâm dữ liệu khác nhau giữa các loại sản phẩm, phản ánh xu hướng tiêu dùng hoặc cơ cấu hàng hóa trong hệ thống dữ liệu.Nhìn chung, dữ liệu tập trung nhiều vào các sản phẩm thiết yếu hoặc thường tiêu thụ như rau quả, đồ ăn vặt, và đồ gia dụng, trong khi các nhóm sản phẩm đặc thù hoặc ít phổ biến lại có số lượng quan sát thấp hơn.
# Tạo bảng tần suất cho biến ProductCategory
freq_tableProductCategory <- table(qual_data$ProductCategory)
# Tính tỷ lệ phần trăm
percent_tableProductCategory <- prop.table(freq_tableProductCategory) * 100
## Tần suất các quan sát của biến City :
##
## 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
## Tỷ lệ phần trăm các quan sát của biến ProductDepartmentu:
##
## Baking Goods Bathroom Products Beer and Wine
## 3.44 2.60 2.53
## Bread Breakfast Foods Candles
## 3.02 2.97 0.32
## Candy Canned Anchovies Canned Clams
## 2.50 0.31 0.38
## Canned Oysters Canned Sardines Canned Shrimp
## 0.25 0.28 0.27
## Canned Soup Canned Tuna Carbonated Beverages
## 2.87 0.62 1.10
## Cleaning Supplies Cold Remedies Dairy
## 1.34 0.66 6.42
## Decongestants Drinks Eggs
## 0.60 0.96 1.41
## Electrical Frozen Desserts Frozen Entrees
## 2.53 2.30 0.84
## Fruit Hardware Hot Beverages
## 5.44 0.92 1.61
## Hygiene Jams and Jellies Kitchen Products
## 1.40 4.18 1.54
## Magazines Meat Miscellaneous
## 1.44 5.41 0.30
## Packaged Vegetables Pain Relievers Paper Products
## 0.34 1.37 2.45
## Pizza Plastic Products Pure Juice Beverages
## 1.38 1.00 1.17
## Seafood Side Dishes Snack Foods
## 0.73 1.09 11.38
## Specialty Starchy Foods Vegetables
## 2.06 1.97 12.29
# Sắp xếp tần suất giảm dần
sorted_freq <- sort(freq_tableProductCategory, decreasing = TRUE)
# Màu sắc đẹp
library(RColorBrewer)
n <- length(sorted_freq)
colors <- colorRampPalette(brewer.pal(9, "Set3"))(n)
# Vẽ biểu đồ thanh ngang
par(mar = c(5, 10, 4, 2)) # Điều chỉnh lề
bar_heights <- barplot(sorted_freq,
horiz = TRUE,
las = 1,
col = colors,
main = "Tần suất các loại ProductCategory",
xlab = "Tần suất",
cex.names = 0.7)
# Chia thành 2 nhóm cho chú thích
half_n <- ceiling(n / 2)
legend_labels1 <- names(sorted_freq)[1:half_n]
legend_labels2 <- names(sorted_freq)[(half_n + 1):n]
legend_colors1 <- colors[1:half_n]
legend_colors2 <- colors[(half_n + 1):n]
# Thêm chú thích gần nhau (vị trí tương đối)
legend(x = "topright",
inset = c(-0.25, 0), # đẩy sang trái
legend = legend_labels1,
fill = legend_colors1,
cex = 0.6,
bty = "n")
legend(x = "topright",
inset = c(-0.05, 0), # đẩy sát bên phải
legend = legend_labels2,
fill = legend_colors2,
cex = 0.6,
bty = "n")
Nhận xét Biến ProductCategory thể hiện sự đa dạng của các nhóm hàng hóa được phân loại theo đặc điểm tiêu dùng. Dữ liệu cho thấy nhóm có tần suất cao nhất là Vegetables với 1.728 lượt quan sát, tiếp theo là Snack Foods (1.600) và Fruit (765), cho thấy đây là những loại sản phẩm được tiêu thụ phổ biến nhất. Ngược lại, các nhóm như Candles (45), Miscellaneous (42), và Canned Oysters (35) có tần suất thấp, phản ánh mức độ tiêu dùng không thường xuyên hoặc ít phổ biến hơn. Các sản phẩm như Dairy (903), Jams and Jellies (588), và Baking Goods (484) cũng nằm trong nhóm có tần suất tương đối cao, cho thấy vai trò quan trọng trong tiêu dùng hàng ngày. Nhìn chung, dữ liệu phản ánh sự ưu tiên của người tiêu dùng đối với các nhóm thực phẩm tươi sống, thực phẩm ăn nhanh và một số mặt hàng thiết yếu trong sinh hoạt.
a. Xác định Hạng mục Quan tâm:
Biến định tính: Gender
Hạng mục quan tâm: “F” (Nữ)
Sử dụng prop.test() để ước lượng khoảng tin cậy 95% cho tỷ lệ nữ trong tổng thể:
gender_table <- table(data$Gender)
n_gender <- sum(gender_table)
x_gender <- gender_table["F"]
# Ước lượng tỷ lệ và khoảng tin cậy 95%
prop.test(x_gender, n_gender, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: x_gender out of n_gender, 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
H0: tỷ lệ nữ trong tổng thể = 0.5
H1: tỷ lệ nữ ≠ 0.5
prop.test(x_gender, n_gender, p = 0.5, alternative = "two.sided")
##
## 1-sample proportions test with continuity correction
##
## data: x_gender out of n_gender, 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
Kết luận:
Nếu p-value < 0.05: Bác bỏ H0, tức tỷ lệ nữ khác 0.5
Nếu p-value ≥ 0.05: Không đủ bằng chứng bác bỏ H0
p-value = 0.0182 < 0.05 (mức ý nghĩa 5%)
Vậy ta bác bỏ H0, cho thấy tỷ lệ nữ trong tổng thể khác 50% (cụ thể là cao hơn một chút theo kết quả mẫu).
Biến Homeowner là biến định tính, thể hiện trạng thái có sở hữu nhà (Y) hoặc không (N).
Hạng mục quan tâm: “Y” (Có sở hữu nhà)
Sử dụng prop.test() để ước lượng khoảng tin cậy 95% cho tỷ lệ người sở hữu nhà trong tổng thể:
home_table <- table(data$Homeowner)
n_home <- sum(home_table)
x_home <- home_table["Y"]
# Ước lượng tỷ lệ và khoảng tin cậy 95%
prop.test(x_home, n_home, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: x_home out of n_home, 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
Khoảng tin cậy 95% là một khoảng giá trị, dựa trên mẫu, cho biết ta có thể tự tin 95% rằng tỷ lệ người sở hữu nhà thực tế trong tổng thể nằm trong khoảng này.
c. Kiểm định Giả thuyết:
H0: tỷ lệ người sở hữu nhà trong tổng thể = 0.6 H1: tỷ lệ người sở hữu nhà ≠ 0.6
prop.test(x_home, n_home, p = 0.6, alternative = "two.sided")
##
## 1-sample proportions test with continuity correction
##
## data: x_home out of n_home, null probability 0.6
## X-squared = 0.019445, df = 1, p-value = 0.8891
## alternative hypothesis: true p is not equal to 0.6
## 95 percent confidence interval:
## 0.5924537 0.6087145
## sample estimates:
## p
## 0.6006117
Kết luận:
Nếu p-value < 0.05: Bác bỏ H0, tức tỷ lệ người sở hữu nhà khác 0.6 Nếu p-value ≥ 0.05: Không đủ bằng chứng bác bỏ H0
p-value = 0.8891 Không đủ bằng chứng bác bỏ H0.Tỷ lệ người sở hữu nhà trong mẫu là khoảng 60.06%.
Khoảng tin cậy 95% cho tỷ lệ này là từ 59.25% đến 60.87%, nghĩa là ta khá chắc chắn tỷ lệ thật trong tổng thể nằm trong khoảng này.
Khi kiểm định giả thuyết tỷ lệ người sở hữu nhà bằng 50%, ta bác bỏ giả thuyết này (p-value rất nhỏ), nghĩa là tỷ lệ người sở hữu nhà thực sự khác xa 50% — nhiều hơn.
Khi kiểm định giả thuyết tỷ lệ người sở hữu nhà bằng 60%, ta không bác bỏ giả thuyết này (p-value lớn), nghĩa là 60% là một tỷ lệ hợp lý và phù hợp với dữ liệu.
Sử dụng prop.test() để ước lượng khoảng tin cậy 95% cho tỷ lệ sản phẩm thuộc nhóm “Food” trong tổng thể:
product_table <- table(data$ProductFamily)
n_product <- sum(product_table)
x_food <- product_table["Food"]
# Ước lượng tỷ lệ và khoảng tin cậy 95%
prop.test(x_food, n_product, conf.level = 0.95)
##
## 1-sample proportions test with continuity correction
##
## data: x_food out of n_product, null probability 0.5
## X-squared = 2774.9, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.7146709 0.7295489
## sample estimates:
## p
## 0.7221709
H0: tỷ lệ sản phẩm “Food” trong tổng thể = 0.7 H1: tỷ lệ sản phẩm “Food” > 0.7
prop.test(x_food, n_product, p = 0.7, alternative = "greater")
##
## 1-sample proportions test with continuity correction
##
## data: x_food out of n_product, null probability 0.7
## X-squared = 32.802, df = 1, p-value = 5.101e-09
## alternative hypothesis: true p is greater than 0.7
## 95 percent confidence interval:
## 0.7158789 1.0000000
## sample estimates:
## p
## 0.7221709
Kết luận:
Nếu p-value < 0.05: Bác bỏ H0, tức tỷ lệ sản phẩm “Food” lớn hơn 0.7 Nếu p-value ≥ 0.05: Không đủ bằng chứng bác bỏ
Vì p-value=5.101e-09 nhỏ hơn mức ý nghĩa 0.05, ta có đủ bằng chứng để bác bỏ giả thuyết H0.
Với mức ý nghĩa 5%, ta bác bỏ giả thuyết rằng tỷ lệ sản phẩm “Food” trong tổng thể bằng 70%. Kết quả cho thấy tỷ lệ sản phẩm “Food” lớn hơn 70% trong tổng thể.
# Tạo bảng tần số
table_gender_pf <- table(data$Gender, data$ProductFamily)
# Tính tỷ lệ phần trăm
prop_gender_pf <- prop.table(table_gender_pf, 1) * 100
prop_gender_pf <- round(prop_gender_pf, 2)
## [1] "Bảng tần số:"
##
## Drink Food Non-Consumable
## F 669 5149 1352
## M 581 5004 1304
## [1] "Tỷ lệ phần trăm(%):"
##
## Drink Food Non-Consumable
## F 9.33 71.81 18.86
## M 8.43 72.64 18.93
# Vẽ biểu đồ cột chồng có thêm số liệu trên cột
library(ggplot2)
# Chuyển bảng sang dạng data frame để vẽ
df_plot <- as.data.frame(table_gender_pf)
colnames(df_plot) <- c("Gender", "ProductFamily", "Frequency")
ggplot(df_plot, aes(x = Gender, y = Frequency, fill = ProductFamily)) +
geom_bar(stat = "identity", position = "stack") +
geom_text(aes(label = Frequency),
position = position_stack(vjust = 0.5),
size = 3, color = "black") +
labs(title = "Biểu đồ cột chồng: Gender vs ProductFamily",
x = "Gender", y = "Tần suất") +
theme_minimal()
# Thực hiện kiểm định Chi-bình phương
chisq_test <- chisq.test(table_gender_pf)
# In kết quả kiểm định
cat("Kết quả kiểm định Chi-bình phương:\n")
## Kết quả kiểm định Chi-bình phương:
cat("Chi-squared =", chisq_test$statistic, "\n")
## Chi-squared = 3.51849
cat("df =", chisq_test$parameter, "\n")
## df = 2
cat("p-value =", chisq_test$p.value, "\n")
## p-value = 0.1721748
# Kết luận
if (chisq_test$p.value < 0.05) {
cat("=> Có mối quan hệ ý nghĩa thống kê giữa Gender và ProductFamily.\n")
} else {
cat("=> Không có mối quan hệ ý nghĩa thống kê giữa Gender và ProductFamily.\n")
}
## => Không có mối quan hệ ý nghĩa thống kê giữa Gender và ProductFamily.
# Tạo bảng tần số
table_ms_home <- table(data$MaritalStatus, data$Homeowner)
# Tính tỷ lệ phần trăm
prop_ms_home <- prop.table(table_ms_home, 1) * 100
prop_ms_home <- round(prop_ms_home, 2)
## [1] "Bảng tần số: MaritalStatus vs Homeowner"
##
## N Y
## M 1719 5147
## S 3896 3297
## [1] "Tỷ lệ phần trăm(%):"
##
## N Y
## M 25.04 74.96
## S 54.16 45.84
# Vẽ biểu đồ cột chồng có nhãn
library(ggplot2)
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
# Dữ liệu chuẩn bị để vẽ
df_plot2 <- as.data.frame(table_ms_home)
colnames(df_plot2) <- c("MaritalStatus", "Homeowner", "Frequency")
# Tính vị trí nhãn
df_plot2 <- df_plot2 %>%
group_by(MaritalStatus) %>%
mutate(pos = cumsum(Frequency) - Frequency / 2)
ggplot(df_plot2, aes(x = MaritalStatus, y = Frequency, fill = Homeowner)) +
geom_bar(stat = "identity", position = "stack") +
geom_text(aes(label = Frequency, y = pos), size = 3, color = "black") +
labs(title = "Biểu đồ cột chồng: MaritalStatus vs Homeowner",
x = "Marital Status", y = "Tần suất") +
theme_minimal()
# Kiểm định Chi-bình phương
chisq_test2 <- chisq.test(table_ms_home)
# In kết quả
cat("Kết quả kiểm định Chi-bình phương (MaritalStatus vs Homeowner):\n")
## Kết quả kiểm định Chi-bình phương (MaritalStatus vs Homeowner):
cat("Chi-squared =", chisq_test2$statistic, "\n")
## Chi-squared = 1241.218
cat("df =", chisq_test2$parameter, "\n")
## df = 1
cat("p-value =", chisq_test2$p.value, "\n")
## p-value = 6.724506e-272
if (chisq_test2$p.value < 0.05) {
cat("=> Có mối quan hệ ý nghĩa thống kê giữa MaritalStatus và Homeowner.\n")
} else {
cat("=> Không có mối quan hệ ý nghĩa thống kê giữa MaritalStatus và Homeowner.\n")
}
## => Có mối quan hệ ý nghĩa thống kê giữa MaritalStatus và Homeowner.
# Tạo bảng tần số
table_income_gender <- table(data$AnnualIncome, data$Gender)
# Tính tỷ lệ phần trăm
prop_income_gender <- prop.table(table_income_gender, 1) * 100
prop_income_gender <- round(prop_income_gender, 2)
print("Bảng tần suất chéo: AnnualIncome vs Gender")
## [1] "Bảng tần suất chéo: AnnualIncome vs Gender"
print(table_income_gender)
##
## F M
## $10K - $30K 1587 1503
## $110K - $130K 307 336
## $130K - $150K 390 370
## $150K + 140 133
## $30K - $50K 2243 2358
## $50K - $70K 1224 1146
## $70K - $90K 959 750
## $90K - $110K 320 293
print("Tỷ lệ phần trăm theo hàng (%):")
## [1] "Tỷ lệ phần trăm theo hàng (%):"
print(prop_income_gender)
##
## F M
## $10K - $30K 51.36 48.64
## $110K - $130K 47.74 52.26
## $130K - $150K 51.32 48.68
## $150K + 51.28 48.72
## $30K - $50K 48.75 51.25
## $50K - $70K 51.65 48.35
## $70K - $90K 56.11 43.89
## $90K - $110K 52.20 47.80
library(dplyr)
library(ggplot2)
# Chuẩn bị dữ liệu
df_plot_income_gender <- as.data.frame(table_income_gender)
colnames(df_plot_income_gender) <- c("AnnualIncome", "Gender", "Frequency")
df_plot_income_gender <- df_plot_income_gender %>%
group_by(AnnualIncome) %>%
mutate(pos = cumsum(Frequency) - Frequency / 2)
# Vẽ biểu đồ
ggplot(df_plot_income_gender, aes(x = AnnualIncome, y = Frequency, fill = Gender)) +
geom_bar(stat = "identity", position = "stack") +
geom_text(aes(label = Frequency, y = pos), size = 3, color = "black") +
labs(title = "Biểu đồ cột chồng: AnnualIncome vs Gender",
x = "Annual Income", y = "Tần suất") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
chisq_test_income_gender <- chisq.test(table_income_gender)
cat("Kết quả kiểm định Chi-bình phương (AnnualIncome vs Gender):\n")
## Kết quả kiểm định Chi-bình phương (AnnualIncome vs Gender):
cat("Chi-squared =", chisq_test_income_gender$statistic, "\n")
## Chi-squared = 30.88325
cat("df =", chisq_test_income_gender$parameter, "\n")
## df = 7
cat("p-value =", chisq_test_income_gender$p.value, "\n")
## p-value = 6.533308e-05
if (chisq_test_income_gender$p.value < 0.05) {
cat("=> Có mối quan hệ ý nghĩa thống kê giữa AnnualIncome và Gender.\n")
} else {
cat("=> Không có mối quan hệ ý nghĩa thống kê giữa AnnualIncome và Gender.\n")
}
## => Có mối quan hệ ý nghĩa thống kê giữa AnnualIncome và Gender.