1. Đọc và làm quen dữ liệu

Cài đặt các gói cần thiết

installed.packages("tidyverse")
##      Package LibPath Version Priority Depends Imports LinkingTo Suggests
##      Enhances License License_is_FOSS License_restricts_use OS_type Archs
##      MD5sum NeedsCompilation Built
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
install.packages("readr")
## Warning: package 'readr' is in use and will not be installed
library(readr)
# Đọc dữ liệu
data <- read_csv("Supermarket Transactions.csv")
## New names:
## Rows: 14059 Columns: 16
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (10): Gender, MaritalStatus, Homeowner, AnnualIncome, City, StateorProv... dbl
## (5): ...1, CustomerID, Children, UnitsSold, Revenue date (1): PurchaseDate
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...1`
# Hiển thị cấu trúc dữ liệu
str(data)
## spc_tbl_ [14,059 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ ...1             : num [1:14059] 1 2 3 4 5 6 7 8 9 10 ...
##  $ PurchaseDate     : Date[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 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   ...1 = col_double(),
##   ..   PurchaseDate = col_date(format = ""),
##   ..   CustomerID = col_double(),
##   ..   Gender = col_character(),
##   ..   MaritalStatus = col_character(),
##   ..   Homeowner = col_character(),
##   ..   Children = col_double(),
##   ..   AnnualIncome = col_character(),
##   ..   City = col_character(),
##   ..   StateorProvince = col_character(),
##   ..   Country = col_character(),
##   ..   ProductFamily = col_character(),
##   ..   ProductDepartment = col_character(),
##   ..   ProductCategory = col_character(),
##   ..   UnitsSold = col_double(),
##   ..   Revenue = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>

Dữ liệu bao gồm: 14059 quan sát và 16 biến.

# Hiển thị một vài dòng đầu và cuối của dữ liệu
head(data)
## # A tibble: 6 × 16
##    ...1 PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
##   <dbl> <date>            <dbl> <chr>  <chr>         <chr>        <dbl>
## 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
## # ℹ 9 more variables: AnnualIncome <chr>, City <chr>, StateorProvince <chr>,
## #   Country <chr>, ProductFamily <chr>, ProductDepartment <chr>,
## #   ProductCategory <chr>, UnitsSold <dbl>, Revenue <dbl>
tail(data)
## # A tibble: 6 × 16
##    ...1 PurchaseDate CustomerID Gender MaritalStatus Homeowner Children
##   <dbl> <date>            <dbl> <chr>  <chr>         <chr>        <dbl>
## 1 14054 2009-12-29         2032 F      M             N                3
## 2 14055 2009-12-29         9102 F      M             Y                2
## 3 14056 2009-12-29         4822 F      M             Y                3
## 4 14057 2009-12-31          250 M      S             Y                1
## 5 14058 2009-12-31         6153 F      S             N                4
## 6 14059 2009-12-31         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>
# Kiểm tra giá trị thiếu (NA)
sum(is.na(data))
## [1] 0

Trong bộ dữ liệu không có giá thiếu (NA).

# Chuyển các biến cần thiết sang kiểu factor
factor_vars <- c("Gender", "MaritalStatus", "Homeowner", "AnnualIncome",
                 "City", "StateorProvince", "Country",
                 "ProductFamily", "ProductDepartment", "ProductCategory")
data[factor_vars] <- lapply(data[factor_vars], as.factor)
# Kiểm tra lại cấu trúc dữ liệu
str(data)
## spc_tbl_ [14,059 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ ...1             : num [1:14059] 1 2 3 4 5 6 7 8 9 10 ...
##  $ PurchaseDate     : Date[1:14059], format: "2007-12-18" "2007-12-20" ...
##  $ CustomerID       : num [1:14059] 7223 7841 8374 9619 1900 ...
##  $ Gender           : Factor w/ 2 levels "F","M": 1 2 1 2 1 1 2 1 2 2 ...
##  $ MaritalStatus    : Factor w/ 2 levels "M","S": 2 1 1 1 2 1 2 1 1 2 ...
##  $ Homeowner        : Factor w/ 2 levels "N","Y": 2 2 1 2 2 2 2 2 2 1 ...
##  $ Children         : num [1:14059] 2 5 2 3 3 3 2 2 3 1 ...
##  $ AnnualIncome     : Factor w/ 8 levels "$10K - $30K",..: 5 7 6 5 3 1 5 4 1 6 ...
##  $ City             : Factor w/ 23 levels "Acapulco","Bellingham",..: 8 8 4 12 3 3 13 23 2 15 ...
##  $ StateorProvince  : Factor w/ 10 levels "BC","CA","DF",..: 2 2 8 6 2 2 6 8 8 2 ...
##  $ Country          : Factor w/ 3 levels "Canada","Mexico",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ ProductFamily    : Factor w/ 3 levels "Drink","Food",..: 2 2 2 2 1 2 2 2 3 3 ...
##  $ ProductDepartment: Factor w/ 22 levels "Alcoholic Beverages",..: 20 18 20 21 4 11 13 6 15 14 ...
##  $ ProductCategory  : Factor w/ 45 levels "Baking Goods",..: 42 45 42 7 15 41 5 13 16 35 ...
##  $ 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 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   ...1 = col_double(),
##   ..   PurchaseDate = col_date(format = ""),
##   ..   CustomerID = col_double(),
##   ..   Gender = col_character(),
##   ..   MaritalStatus = col_character(),
##   ..   Homeowner = col_character(),
##   ..   Children = col_double(),
##   ..   AnnualIncome = col_character(),
##   ..   City = col_character(),
##   ..   StateorProvince = col_character(),
##   ..   Country = col_character(),
##   ..   ProductFamily = col_character(),
##   ..   ProductDepartment = col_character(),
##   ..   ProductCategory = col_character(),
##   ..   UnitsSold = col_double(),
##   ..   Revenue = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>

2.Phân tích mô tả một biến định tính

2.1 Biến Gender

# Bảng tần số và tần suất
library(dplyr)
gender_freq <- data %>%
  count(Gender) %>%
  mutate(
    Gender = factor(Gender, levels = c("F", "M"), labels = c("Nữ", "Nam")),
    `Tần số` = n,
    `Tần suất (%)` = round(n / sum(n) * 100, 2)
  ) %>%
  select(Giới_tính = Gender, `Tần số`, `Tần suất (%)`)

gender_freq
## # A tibble: 2 × 3
##   Giới_tính `Tần số` `Tần suất (%)`
##   <fct>        <int>          <dbl>
## 1 Nữ            7170             51
## 2 Nam           6889             49
# Vẽ biểu đồ 
library(ggplot2)
library(dplyr)
gender_freq <- data %>%
  count(Gender) %>%
  mutate(Gender = factor(Gender, levels = c("F", "M"), labels = c("Nữ", "Nam")))
  ggplot(gender_freq, aes(x = Gender, y = n)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "black") +
  geom_text(aes(label = n), vjust = -0.5, size = 5) +
  labs(
    title = "Biểu đồ Tần suất Giới tính Khách hàng",
    x = "Giới tính",
    y = "Tần suất (số lượng)",
    caption = "Nam = M, Nữ = F"
  ) +
  theme_minimal()

2.2 Biến MaritalStatus

# Bảng tần số và tần suất
MaritalStatus_freq <- data %>% 
  count(MaritalStatus) %>% 
  mutate(
    MaritalStatus = factor(MaritalStatus, levels = c("S", "M"), labels = c("Kết hôn", "Độc thân")), 
    "Tần số" = n,
    "Tần suất (%)" = round(n / sum(n) * 100, 2)
  ) %>%
  select(Tỷ_lệ_độc_thân = MaritalStatus, "Tần số", "Tần suất (%)")
  MaritalStatus_freq
## # A tibble: 2 × 3
##   Tỷ_lệ_độc_thân `Tần số` `Tần suất (%)`
##   <fct>             <int>          <dbl>
## 1 Độc thân           6866           48.8
## 2 Kết hôn            7193           51.2
  # Vẽ biểu đồ 
MaritalStatus_freq <- data.frame(
  MaritalStatus = c("Độc thân", "Kết hôn"),
  Frequency = c(6866, 7193)
)
ggplot(MaritalStatus_freq, aes(x = MaritalStatus, y = Frequency)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "black") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 5) +
  labs(
    title = "Biểu đồ tình trạng độc thân",
    x = "Tình trạng",
    y = "Tần suất",
    caption = "Độc thân = M, Kết hôn = S"
  ) +
  theme_minimal()

2.3 Biến Homeowner

# Bảng tần số và tần suất
Homeowner_freq <- data %>% 
  count(Homeowner) %>% 
  mutate(
   Homeowner = factor(Homeowner, levels = c("Y", "N"), labels = c("Có", "Không")), 
    "Tần số" = n,
    "Tần suất (%)" = round(n / sum(n) * 100, 2)
  ) %>%
  select(Trạng_thái_sở_hữu_nhà = Homeowner, "Tần số", "Tần suất (%)")
Homeowner_freq
## # A tibble: 2 × 3
##   Trạng_thái_sở_hữu_nhà `Tần số` `Tần suất (%)`
##   <fct>                    <int>          <dbl>
## 1 Không                     5615           39.9
## 2 Có                        8444           60.1
# Vẽ biểu đồ 
Homeowner_freq <- data.frame(
  Homeowner = c("Có", "Không"),
  Frequency = c(5615, 8444)
)
ggplot(Homeowner_freq, aes(x =Homeowner, y = Frequency)) +
  geom_bar(stat = "identity", fill = "skyblue", color = "black") +
  geom_text(aes(label = Frequency), vjust = -0.5, size = 5) +
  labs(
    title = "Biểu đồ tình trạng sở hữu nhà",
    x = "Tình trạng",
    y = "Tần suất ",
    caption = "Có = Y, Không = N"
  ) +
  theme_minimal()

2.4 Biến AnnualIncome

# Bảng tần số và tần suất
AnnualIncome_levels <- c(
  "$10K - $30K", "$30K - $50K", "$50K - $70K", "$70K - $90K", 
  "$90K - $110K", "$110K - $130K", "$130K - $150K", "$150K +"
)
AnnualIncome_freq <- data %>%
  mutate(AnnualIncome = factor(AnnualIncome, levels = AnnualIncome_levels)) %>%
  count(AnnualIncome) %>%
  mutate(
    Tan_so = n,
    Tan_suat = round(n / sum(n) * 100, 2)
  ) %>%
  select(Muc_thu_nhap = AnnualIncome, Tan_so, Tan_suat)

AnnualIncome_freq
## # A tibble: 8 × 3
##   Muc_thu_nhap  Tan_so Tan_suat
##   <fct>          <int>    <dbl>
## 1 $10K - $30K     3090    22.0 
## 2 $30K - $50K     4601    32.7 
## 3 $50K - $70K     2370    16.9 
## 4 $70K - $90K     1709    12.2 
## 5 $90K - $110K     613     4.36
## 6 $110K - $130K    643     4.57
## 7 $130K - $150K    760     5.41
## 8 $150K +          273     1.94
# Vẽ biểu đồ 
ggplot(AnnualIncome_freq, aes(x = Muc_thu_nhap, y = Tan_so)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = Tan_so), vjust = -0.5, size = 4) +
  labs(
    title = "Tần số theo mức thu nhập",
    x = "Mức thu nhập",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

##2.5 Biến City

# Bảng tần số và tần suất
City_levels <- c(
  "Acapulco", "Bellingham", "Beverly Hills", "Bremerton", 
  "Camacho", "Guadalajara", "Hidalgo", "Los Angeles","Merida","Mexico City","Orizaba","Portland","Salem","San Andres","San Diego","San Francisco","Seattle","Spokane","Tacoma","Vancouver","Victoria","Walla Walla","Yakima"
)
City_freq <- data %>%
  mutate(City = factor(City, levels = City_levels)) %>%
  count(City) %>%
  mutate(
    TanSo = n,
    TanSuat = round(n / sum(n) * 100, 2)
  ) %>%
  select(ThanhPho = City, TanSo, TanSuat)
City_freq
## # A tibble: 23 × 3
##    ThanhPho      TanSo TanSuat
##    <fct>         <int>   <dbl>
##  1 Acapulco        383    2.72
##  2 Bellingham      143    1.02
##  3 Beverly Hills   811    5.77
##  4 Bremerton       834    5.93
##  5 Camacho         452    3.22
##  6 Guadalajara      75    0.53
##  7 Hidalgo         845    6.01
##  8 Los Angeles     926    6.59
##  9 Merida          654    4.65
## 10 Mexico City     194    1.38
## # ℹ 13 more rows
print(City_freq, n = 23)
## # A tibble: 23 × 3
##    ThanhPho      TanSo TanSuat
##    <fct>         <int>   <dbl>
##  1 Acapulco        383    2.72
##  2 Bellingham      143    1.02
##  3 Beverly Hills   811    5.77
##  4 Bremerton       834    5.93
##  5 Camacho         452    3.22
##  6 Guadalajara      75    0.53
##  7 Hidalgo         845    6.01
##  8 Los Angeles     926    6.59
##  9 Merida          654    4.65
## 10 Mexico City     194    1.38
## 11 Orizaba         464    3.3 
## 12 Portland        876    6.23
## 13 Salem          1386    9.86
## 14 San Andres      621    4.42
## 15 San Diego       866    6.16
## 16 San Francisco   130    0.92
## 17 Seattle         922    6.56
## 18 Spokane         875    6.22
## 19 Tacoma         1257    8.94
## 20 Vancouver       633    4.5 
## 21 Victoria        176    1.25
## 22 Walla Walla     160    1.14
## 23 Yakima          376    2.67
# Vẽ biểu đồ
ggplot(City_freq, aes(x = ThanhPho, y = TanSo)) +
  geom_col(fill = "steelblue") +  
  geom_text(aes(label = TanSo), vjust = -0.5, size = 4) + 
  labs(
    title = "Số lượng khách hàng tại các thành phố",
    x = "Thành phố",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 70, hjust = 1))

2.6 Biến StateorProvince

# Bảng tần số và tần suất
StateorProvince_levels <- c(
  "BC", "CA", "DF", "Guerrero", 
  "Jalisco", "OR", "Veracruz", "WA","Yucatan","Zacatecas"
)
StateorProvince_freq <- data %>%
  mutate(StateorProvince = factor(StateorProvince, levels = StateorProvince_levels)) %>%
  count(StateorProvince) %>%
  mutate(
    "Tần số" = n,
    "Tần suất (%)" = round(n / sum(n) * 100, 2)
  ) %>%
  select("Các Bang" =StateorProvince, "Tần số", "Tần suất (%)")
StateorProvince_freq
## # A tibble: 10 × 3
##    `Các Bang` `Tần số` `Tần suất (%)`
##    <fct>         <int>          <dbl>
##  1 BC              809           5.75
##  2 CA             2733          19.4 
##  3 DF              815           5.8 
##  4 Guerrero        383           2.72
##  5 Jalisco          75           0.53
##  6 OR             2262          16.1 
##  7 Veracruz        464           3.3 
##  8 WA             4567          32.5 
##  9 Yucatan         654           4.65
## 10 Zacatecas      1297           9.23
print(StateorProvince_freq, n = 10)
## # A tibble: 10 × 3
##    `Các Bang` `Tần số` `Tần suất (%)`
##    <fct>         <int>          <dbl>
##  1 BC              809           5.75
##  2 CA             2733          19.4 
##  3 DF              815           5.8 
##  4 Guerrero        383           2.72
##  5 Jalisco          75           0.53
##  6 OR             2262          16.1 
##  7 Veracruz        464           3.3 
##  8 WA             4567          32.5 
##  9 Yucatan         654           4.65
## 10 Zacatecas      1297           9.23
# Vẽ biểu đồ
ggplot(StateorProvince_freq, aes(x = `Các Bang`, y = `Tần số`)) +
  geom_col(fill = "steelblue") +  
  geom_text(aes(label =  "Tần số"),
            vjust = -0.5, size = 4) + 
  labs(
    title = "Số lượng khách hàng tại các Bang",
    x = "Các Bang",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

2.7 Biến Country

# Bảng tần số và tần suất
Country_levels <- c(
  "Canada", "Mexico", "USA"
)
Country_freq <- data %>%
  mutate(Country = factor(Country, levels = Country_levels)) %>%
  count(Country) %>%
  mutate(
    TanSo = n,
    TanSuat = round(n / sum(n) * 100, 2)
  ) %>%
  select(QuocGia = Country, TanSo, TanSuat)
Country_freq
## # A tibble: 3 × 3
##   QuocGia TanSo TanSuat
##   <fct>   <int>   <dbl>
## 1 Canada    809    5.75
## 2 Mexico   3688   26.2 
## 3 USA      9562   68.0
# Vẽ biểu đồ  
 ggplot(Country_freq, aes(x = QuocGia, y = TanSo)) +
  geom_col(fill = "steelblue") +  
  geom_text(aes(label = TanSo), vjust = -0.5, size = 4) + 
  labs(
    title = "Số lượng khách hàng tại các Quốc gia",
    x = "Quốc gia",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

2.8 Biến ProductFamily

# Bảng tần số và tần suất
ProductFamily_levels <- c(
  "Food", "Drink", "Non-Consumable"
)
ProductFamily_freq <- data %>%
  mutate(ProductFamily = factor(ProductFamily, levels = ProductFamily_levels)) %>%
  count(ProductFamily) %>%
  mutate(
    TanSo = n,
    TanSuat = round(n / sum(n) * 100, 2)
  ) %>%
  select(NhomSanPham = ProductFamily, TanSo, TanSuat)
ProductFamily_freq
## # A tibble: 3 × 3
##   NhomSanPham    TanSo TanSuat
##   <fct>          <int>   <dbl>
## 1 Food           10153   72.2 
## 2 Drink           1250    8.89
## 3 Non-Consumable  2656   18.9
# Vẽ biểu đồ 
  ggplot(ProductFamily_freq, aes(x = NhomSanPham, y = TanSo)) +
  geom_col(fill = "steelblue") +  
  geom_text(aes(label = TanSo),
            vjust = -0.5, size = 4) + 
  labs(
    title = "Nhóm sản phẩm chủ yếu",
    x = "Nhóm sản phẩm chủ yếu",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

2.9 Biến ProductDepartment

# Bảng tần số và tần suất
ProductDepartment_levels <- c(
  "Alcoholic Beverages", "Baked Goods", "Baking Goods","Beverages","Breakfast Foods","Canned Foods","Canned Products","Carousel","Checkout","Dairy","Deli","Eggs","Frozen Foods","Health and Hygiene","Household","Meat","Periodicals","Produce","Seafood","Snack Foods","Snacks","Starchy Foods"
)
ProductDepartment_freq <- data %>%
  mutate(ProductDepartment = factor(ProductDepartment, levels = ProductDepartment_levels)) %>%
  count(ProductDepartment) %>%
  mutate(
    TanSo = n,
    TanSuat = round(n / sum(n) * 100, 2)
  ) %>%
  select(SanPham = ProductDepartment, TanSo, TanSuat)
ProductDepartment_freq
## # A tibble: 22 × 3
##    SanPham             TanSo TanSuat
##    <fct>               <int>   <dbl>
##  1 Alcoholic Beverages   356    2.53
##  2 Baked Goods           425    3.02
##  3 Baking Goods         1072    7.63
##  4 Beverages             680    4.84
##  5 Breakfast Foods       188    1.34
##  6 Canned Foods          977    6.95
##  7 Canned Products       109    0.78
##  8 Carousel               59    0.42
##  9 Checkout               82    0.58
## 10 Dairy                 903    6.42
## # ℹ 12 more rows
print(ProductDepartment_freq, n = 22)
## # A tibble: 22 × 3
##    SanPham             TanSo TanSuat
##    <fct>               <int>   <dbl>
##  1 Alcoholic Beverages   356    2.53
##  2 Baked Goods           425    3.02
##  3 Baking Goods         1072    7.63
##  4 Beverages             680    4.84
##  5 Breakfast Foods       188    1.34
##  6 Canned Foods          977    6.95
##  7 Canned Products       109    0.78
##  8 Carousel               59    0.42
##  9 Checkout               82    0.58
## 10 Dairy                 903    6.42
## 11 Deli                  699    4.97
## 12 Eggs                  198    1.41
## 13 Frozen Foods         1382    9.83
## 14 Health and Hygiene    893    6.35
## 15 Household            1420   10.1 
## 16 Meat                   89    0.63
## 17 Periodicals           202    1.44
## 18 Produce              1994   14.2 
## 19 Seafood               102    0.73
## 20 Snack Foods          1600   11.4 
## 21 Snacks                352    2.5 
## 22 Starchy Foods         277    1.97
# Vẽ biểu đồ
ggplot(ProductDepartment_freq, aes(x = SanPham, y = TanSo)) +
  geom_col(fill = "steelblue") +  
  geom_text(aes(label = TanSo),  
            vjust = -0.5, size = 4) + 
  labs(
    title = "Phòng ban sản phẩm",
    x = "Sản phẩm",
    y = "Tần số"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

2.10 Biến ProductCategory

# Bảng tần số và tần suất
ProductCategory_levels <- c(
  "Baking Goods", "Bathroom Products", "Beer and Wine","Bread","Breakfast Foods","Candles","Candy","Canned Anchovies","Canned Clams","Canned Oysters","Canned Sardines","Canned Shrimp","Canned Soup","Canned Tuna","Carbonated Beverages","Cleaning Supplies","Cold Remedies","Dairy","Decongestants","Drinks","Eggs","Electrical","Frozen Desserts","Frozen Entrees","Fruit","Hardware","Hot Beverages","Hygiene","Jams and Jellies","Kitchen Products","Magazines","Meat","Miscellaneous","Packaged Vegetables","Pain Relievers","Paper Products","Pizza","Plastic Products","Pure Juice Beverages","Seafood","Side Dishes","Snack Foods","Specialty","Starchy Foods","Vegetables"
)
ProductCategory_freq <- data %>%
  mutate(ProductCategory = factor(ProductCategory, levels = ProductCategory_levels)) %>%
  count(ProductCategory) %>%
  mutate(
    TanSo = n,
    TanSuat = round(n / sum(n) * 100, 2)
  ) %>%
  select(SanPham = ProductCategory, TanSo, TanSuat)
ProductCategory_freq
## # A tibble: 45 × 3
##    SanPham           TanSo TanSuat
##    <fct>             <int>   <dbl>
##  1 Baking Goods        484    3.44
##  2 Bathroom Products   365    2.6 
##  3 Beer and Wine       356    2.53
##  4 Bread               425    3.02
##  5 Breakfast Foods     417    2.97
##  6 Candles              45    0.32
##  7 Candy               352    2.5 
##  8 Canned Anchovies     44    0.31
##  9 Canned Clams         53    0.38
## 10 Canned Oysters       35    0.25
## # ℹ 35 more rows
print(ProductCategory_freq, n = 45)
## # A tibble: 45 × 3
##    SanPham              TanSo TanSuat
##    <fct>                <int>   <dbl>
##  1 Baking Goods           484    3.44
##  2 Bathroom Products      365    2.6 
##  3 Beer and Wine          356    2.53
##  4 Bread                  425    3.02
##  5 Breakfast Foods        417    2.97
##  6 Candles                 45    0.32
##  7 Candy                  352    2.5 
##  8 Canned Anchovies        44    0.31
##  9 Canned Clams            53    0.38
## 10 Canned Oysters          35    0.25
## 11 Canned Sardines         40    0.28
## 12 Canned Shrimp           38    0.27
## 13 Canned Soup            404    2.87
## 14 Canned Tuna             87    0.62
## 15 Carbonated Beverages   154    1.1 
## 16 Cleaning Supplies      189    1.34
## 17 Cold Remedies           93    0.66
## 18 Dairy                  903    6.42
## 19 Decongestants           85    0.6 
## 20 Drinks                 135    0.96
## 21 Eggs                   198    1.41
## 22 Electrical             355    2.53
## 23 Frozen Desserts        323    2.3 
## 24 Frozen Entrees         118    0.84
## 25 Fruit                  765    5.44
## 26 Hardware               129    0.92
## 27 Hot Beverages          226    1.61
## 28 Hygiene                197    1.4 
## 29 Jams and Jellies       588    4.18
## 30 Kitchen Products       217    1.54
## 31 Magazines              202    1.44
## 32 Meat                   761    5.41
## 33 Miscellaneous           42    0.3 
## 34 Packaged Vegetables     48    0.34
## 35 Pain Relievers         192    1.37
## 36 Paper Products         345    2.45
## 37 Pizza                  194    1.38
## 38 Plastic Products       141    1   
## 39 Pure Juice Beverages   165    1.17
## 40 Seafood                102    0.73
## 41 Side Dishes            153    1.09
## 42 Snack Foods           1600   11.4 
## 43 Specialty              289    2.06
## 44 Starchy Foods          277    1.97
## 45 Vegetables            1728   12.3
# Vẽ biểu đồ
library(ggplot2)
library(stringr)
ggplot(ProductCategory_freq, aes(x = SanPham, y = TanSo)) +
  geom_col(fill = "steelblue") +
  geom_text(aes(label = TanSo), hjust = -0.1, size = 3) +
  labs(title = "Danh mục sản phẩm", x = "Sản phẩm", y = "Tần số") +
  theme_minimal() +
  coord_flip() +
  theme(axis.text.y = element_text(size = 7, hjust = 1))

3.Ước lượng Khoảng và Kiểm định Giả thuyết cho Tỷ lệ (Một biến) 3.1 Tính số lượng và tỷ lệ hạng mục quan tâm

# Đếm số lượng hạng mục quan tâm trong tổng dữ liệu
n_total <- nrow(data)  # tổng số quan sát
# Gender = "F"
n_female <- sum(data$Gender == "F", na.rm = TRUE)
prop_female <- n_female / n_total
# Homeowner = "Y"
n_homeowner <- sum(data$Homeowner == "Y", na.rm = TRUE)
prop_homeowner <- n_homeowner / n_total
# ProductFamily = "Food"
n_food <- sum(data$ProductFamily == "Food", na.rm = TRUE)
prop_food <- n_food / n_total
# In ra số liệu
cat("Female:", n_female, ", Tỷ lệ:", prop_female, "\n")
## Female: 7170 , Tỷ lệ: 0.5099936
cat("Homeowner:", n_homeowner, ", Tỷ lệ:", prop_homeowner, "\n")
## Homeowner: 8444 , Tỷ lệ: 0.6006117
cat("Food product:", n_food, ", Tỷ lệ:", prop_food, "\n")
## Food product: 10153 , Tỷ lệ: 0.7221709
  • Trong tổng số dữ liệu, có 7.170 khách hàng là nữ, chiếm khoảng 51% tổng số, gần bằng tỷ lệ 50% giả định ban đầu. Điều này cho thấy phân bố giới tính trong dữ liệu khá cân bằng, không lệch nhiều về phía nam hay nữ.
  • Có 8.444 khách hàng được ghi nhận là chủ nhà, chiếm hơn 60% tổng thể, đúng với giả định tỷ lệ chủ nhà là 60%. Đây là tín hiệu cho thấy phần lớn khách hàng có khả năng sở hữu nhà riêng, có thể ảnh hưởng đến hành vi tiêu dùng của họ.
  • Nhóm sản phẩm “Food” chiếm ưu thế rõ rệt với 10.153 giao dịch, tương đương tỷ lệ hơn 72%, vượt qua mức giả định 70%. Điều này chứng tỏ mặt hàng thực phẩm là nhóm được ưa chuộng nhất trong bộ dữ liệu này. 3.2 Ước lượng khoảng tin cậy 95% cho tỷ lệ
# Khoảng tin cậy cho Female
ci_female <- prop.test(n_female, n_total)$conf.int
# Khoảng tin cậy cho Homeowner
ci_homeowner <- prop.test(n_homeowner, n_total)$conf.int
# Khoảng tin cậy cho Food product
ci_food <- prop.test(n_food, n_total)$conf.int
# In ra khoảng tin cậy
cat("Khoảng tin cậy 95% Female:", ci_female, "\n")
## Khoảng tin cậy 95% Female: 0.5016931 0.5182886
cat("Khoảng tin cậy 95% Homeowner:", ci_homeowner, "\n")
## Khoảng tin cậy 95% Homeowner: 0.5924537 0.6087145
cat("Khoảng tin cậy 95% Food product:", ci_food, "\n")
## Khoảng tin cậy 95% Food product: 0.7146709 0.7295489
  • Khoảng tin cậy 95% cho tỷ lệ khách hàng nữ dao động từ khoảng 50.17% đến 51.83%, cho thấy tỷ lệ nữ trong tổng thể khá ổn định và gần một nửa. Tỷ lệ này phản ánh sự cân bằng giới tính trong mẫu khách hàng.
  • Khoảng tin cậy cho tỷ lệ chủ nhà (Homeowner) nằm trong khoảng từ 59.25% đến 60.87%, cho thấy đa số khách hàng trong dữ liệu là chủ nhà, điều này có thể ảnh hưởng đến hành vi mua sắm và lựa chọn sản phẩm.
  • Khoảng tin cậy cho tỷ lệ khách hàng mua sản phẩm thuộc nhóm Food dao động từ 71.47% đến 72.95%, thể hiện rằng sản phẩm thực phẩm chiếm tỷ trọng lớn trong tổng số giao dịch, là nhóm sản phẩm chủ lực của siêu thị. => Nhìn chung, các khoảng tin cậy đều khá hẹp, chứng tỏ độ tin cậy cao và dữ liệu có kích thước mẫu đủ lớn để ước lượng chính xác tỷ lệ các nhóm khách hàng và sản phẩm quan tâm. 3.3 Kiểm định giả thuyết về tỷ lệ Bài toán kiểm định Đặt giải thuyết Giả thuyết không (H₀):
  • Với Gender - Female(F): H0: Tỷ lệ nữ là 0.5 (50%) H1: Tỷ lệ nữ ≠ 0.5
  • Với Homeowner - Yes (Y): H0: Tỷ lệ chủ nhà là 0.6 (60%) H1: Tỷ lệ chủ nhà ≠ 0.6
  • Với Food Product - Food H0: Tỷ lệ mua sản phẩm Food ≥ 0.7 (70%) H1: Tỷ lệ mua sản phẩm Food < 0.7 Mức ý nghĩa: α = 0.05
# Kiểm định tỷ lệ nữ = 0.5
test_female <- prop.test(n_female, n_total, p = 0.5, alternative = "two.sided")
# Kiểm định tỷ lệ chủ nhà = 0.6
test_homeowner <- prop.test(n_homeowner, n_total, p = 0.6, alternative = "two.sided")
# Kiểm định tỷ lệ Food >= 0.7 (kiểm định một phía)
test_food <- prop.test(n_food, n_total, p = 0.7, alternative = "greater")
# In kết quả kiểm định
cat("Kiểm định Female:\n")
## Kiểm định Female:
print(test_female)
## 
##  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
cat("\nKiểm định Homeowner:\n")
## 
## Kiểm định Homeowner:
print(test_homeowner)
## 
##  1-sample proportions test with continuity correction
## 
## data:  n_homeowner out of n_total, 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
cat("\nKiểm định Food product:\n")
## 
## Kiểm định Food product:
print(test_food)
## 
##  1-sample proportions test with continuity correction
## 
## data:  n_food out of n_total, 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
  • Giới tính (Female): Tỷ lệ khách hàng là nữ là 50.99936%, với khoảng tin cậy 95% từ 50.17% đến 51.83%. Kết quả kiểm định cho p-value = 0.0182 nhỏ hơn mức ý nghĩa 0.05, do đó bác bỏ giả thuyết H₀: p = 0.5. Có bằng chứng thống kê cho thấy tỷ lệ nữ trong tập dữ liệu khác 50%, dù sự chênh lệch không lớn.
  • Chủ sở hữu nhà (Homeowner): Tỷ lệ khách hàng sở hữu nhà là 60.06117%, với khoảng tin cậy 95% từ 59.25% đến 60.87%. P-value = 0.8891, lớn hơn 0.05 nên không bác bỏ giả thuyết H₀: p = 0.6. Điều này cho thấy tỷ lệ chủ nhà trong mẫu không khác biệt đáng kể so với tỷ lệ giả định 60%.
  • Sản phẩm Food: Tỷ lệ khách hàng mua sản phẩm thuộc nhóm Food là 72.21709%, với khoảng tin cậy 95% từ 71.59% đến 100%. Kiểm định cho p-value = 5.101e-09 rất nhỏ so với 0.05 nên bác bỏ giả thuyết H₀: p ≤ 0.7, đồng thời chấp nhận H₁: p > 0.7. Như vậy, có bằng chứng mạnh cho thấy tỷ lệ mua sản phẩm Food thực sự lớn hơn 70%.